Instantsearch.js Submit hide on search? - algolia

Problem:
By default in instantsearch.js, the reset button in the search field is hidden until you start typing. However the submit button doesn't hide, causing them to overlap, this seems default behavior(?)
Here is a demo that demonstrates the issue:
https://codesandbox.io/s/quizzical-leakey-7shzr
Expected Outcome:
I want the search submit button to replace (toggle) with the reset button on typing.
Things I've tried:
I have looked through the documentation and can't find any solution to this. There is a showReset and showSubmit parameters as seen here: https://www.algolia.com/doc/api-reference/widgets/search-box/js/ but these just disable them completely.
Changing the template for them in the widget, only stylizes them, rather than adjust their function.
I do have a heavy handed solution I've written in jquery below but my question is: Is there a way to configure this behavior in instantsearch.js?
$( ".ais-SearchBox-input" ).on("keyup", function() {
if($('.ais-SearchBox-input').val().length > 0){
$('.ais-SearchBox-submit').addClass('none');
}else{
$('.ais-SearchBox-submit').removeClass('none');
}
});
$(document).on('click', '.ais-SearchBox-reset', function() {
$('.ais-SearchBox-submit').removeClass('none');
});

The submit button is initially designed to be on the left hand side of the searchbox, and the reset one on the right hand side, as you can see in the InstantSearch.js SearchBox Storybook. In your demo, there's custom CSS that aligns them both on the right, which is why they're overlapping. But they're two orthogonal concepts, so they weren't designed to replace one another out of the box.
Your solution is fine, although I understand that having imperative logic like this on top of InstantSearch.js might feel icky. Another approach is to directly hook into the rendering logic of the widget by using the connectSearchBox connector. You'll be able to fully control what is rendered, and you'll have access to query which you'll be able to leverage to decide whether to show one button or the other.
My advice is to start from the full example and adapt it for your use case.

Related

My question is about Ability for an author to reorder each tab within the component dialog in aem

enter image description here
I want to know how to provide the numbering for each tab, so that author can provide the number as per their requirement.
This is the strangest requirement I ever heard of. You can sure do that, but it didn't make much sense of doing it system wide as one author can feel the dialog one way, other in completely different. The only reasonable solution is to use javascript to reorder the tabs in the way an author want and than save the settings for this specific component in his user profile. You can start implementing it by creating a clientlib with the category cq.authoring.dialog. In your JS you have to listen to specific dialog loading event as shown below. I think this should be enough and it's a good starting point.
// necessary as no granite or coral ui event is triggered, when the dialog is opened
// in a fullscreen mode the dialog is opened under specific url for serving devices with low screen resolution
if (location.href.match(/mnt\/override/)) {
$(window).on('load', function(e) {
setTimeout(doSomething, 100);
});
} else {
$(document).on('dialog-ready', function(e) {
Coral.commons.ready(function(){
setTimeout(doSomething, 100);
});
});
}
You can use granite:rel to define specific identifiers in the dialog definition and use save them later in the user settings. You can define drag & drop events using the tab selector [role="tab"].
This is not trivially possible. Decide upfront about the order when building the component, provide meaningful labels and go with that. Touch UI does not provide the feature you need.

Addon SDK way to make a dialog

What is the proper way to use the SDK to make a dialog (which is not anchored to the add-on bar, etc. but shows centered on screen)? It doesn't seem like there is any API for this important capability. I do see windows/utils has open but I have two problems with that:
The dialog opening seems to require "chrome" privs to get it to be centered on the screen (and I'd be expectant of add-on reviewers complaining of chrome privs, and even if not, I'd like to try to stick to the SDK way).
While I can get the DOM window reference of the new window/utils' open() dialog, I'm not sure how to attach a content script so I can respond to user interaction in a way that prompts (and can respond to) privileged behavior ala postMessage or port.emit (without again, directly working with chrome privs).
Ok, this answer should have been pretty obvious for anyone with a little experience with the SDK. I realized I can just use a panel. In my defense, the name "panel" is not as clear as "dialog" in conjuring up this idea, and I am so used to using panels with widgets, that it hadn't occurred to me that I could use it independently!
Edit
Unfortunately, as per Bug 595040, these dialogs are not persistent, meaning if the panel loses focus, the "dialog" is gone... So panel looks like it is not a suitable candidate after all... :(
Edit 2
I've since moved on and have gotten things working mostly to my satisfaction with sdk/window/utils and openDialog on whose returned window I add a load listener and then call tabs.activeTab.on('ready', and then set tabs.activeTab.url to my add-on local HTML file so the ready event will get a tab to which I can attach a worker. There is still the problem with chrome privs I suppose, but at least the main communications are using SDK processes.
Update to Edit 2:
Code sample provided by request:
var data = require('sdk/self').data,
tabs = require('sdk/tabs');
var win = require('sdk/window/utils').openDialog({
// No "url" supplied here in this case as we add it below (in order to have a ready listener in place before load which can give us access to the tab worker)
// For more, see https://developer.mozilla.org/en-US/docs/Web/API/window.open#Position_and_size_features
features: Object.keys({
chrome: true, // Needed for centerscreen per docs
centerscreen: true, // Doesn't seem to be working for some reason (even though it does work when calling via XPCOM)
resizable: true,
scrollbars: true
}).join() + ',width=850,height=650',
name: "My window name"
// parent:
// args:
});
win.addEventListener('load', function () {
tabs.activeTab.on('ready', function (tab) {
var worker = tab.attach({
contentScriptFile: ....
// ...
});
// Use worker.port.on, worker.port.emit, etc...
});
tabs.activeTab.url = data.url('myHTMLFile.html');
});
if the panel loses focus, the "dialog" is gone...
It doesn't get destroyed, just hides, right? If so, depending on why it's getting hidden, you can just call show() on it again.
You'd want to make sure it's not being hidden for a good reason before calling show again. If there's a specific situation in which it's losing focus where you don't want it to, create a listener for that situation, then call if (!panel.isShown) panel.show();
For example, if it's losing focus because a user clicks outside the box, then that's probably the expected behaviour and nothing should be done. If it's losing focus when the browser/tab loses focus, just register a tab.on('activate', aboveFunction)
Simply adding ",screenX=0,screenY=0" (or any values, the zeroes seem to be meaningless) to the features screen seems to fix centerscreen.

form textbox - keep focus during page load

On my homepage I have a form with a search textbox. If you click on the input and start typing when the page in still loading, something steals the focus so you have to click back in the input textbox.
Is there a way to prevent this from happening? Do I need to find what is stealing the focus?
Sounds like one of your scripts is setting something to focus on load.
Put this at the bottom of your HTML right before </body>. Your console will show you the HTML of the item that is gaining focus.
<script>
$(window).load(function() { // NB not document ready
console.log($(':focus')[0]);
// alert($(':focus')[0]); // if you don't know what console is
});
</script>
Hopefully there will be an ID in the element that you can search your script for, or enough clues to let you find what's being told to focus on load. Then you can remove/alter that line.
Addendum
It turns out this is the culprit
$('#f input#livesearch').clearableTextField();
That clearable function is only ever going to be required if the user uses that field, so let's make it contextual, i.e. only when it's given focus, make that function available. This should stop the naughty plugin stealing focus.
$('#f input#livesearch').on('focus', function(){
$(this).clearableTextField();
});
It's generally best to write contextually - you'll find pages with dozens of binds and "live" events being set up on onload, but they are rarely used. If it's something that doesn't need to happen until the user does something or until you can tell a user is about to do something, write it that way.

mousedown event on options in select with jquery .on

I was reading the documentation of the .on event handler of jQuery and I started playing around with it.
I have a simple <select> element with the multiple attribute set to true.
However, I want the user to be able to select multiple items without having to press the ctrl or shift key(s)
According to the .on documentation, if you specify a selector it will automatically add those event handlers to any new items added inside that container that match the selector specified.
So in my case, I could for example decide to replace the <option> elements available in the listbox, but I still want to have the same functionality for those options without having to rebind those events etc.
One might think that the following snippet should do the trick (atleast, I did):
$('#dropdownlist').on('mousedown', 'option', function(e){
e.preventDefault();
$(this).prop('selected', $(this).prop('selected') ? false : true);
return false;
});
So when a users clicks on an option in that listbox, the default action will be cancelled and depending wether the item is already selected or not, it will invert that selection.
I have created a small fiddle demonstrating this behaviour: fiddle
In that fiddle, the first dropdownlist is behaving as expected, but the functionality is lost when replacing the items. This only works in FF & Chrome.
The second dropdownlist is how I thought it should've been (event handling wise), but that doesn't seem to work besides in Chrome -.-
The functionality is kept when replacing items, because the console will still log '2' when clicking on an item after replacing them.
Can someone explain me why this is happening? Am I doing something wrong?
Please point me in the right direction!
Thanks!
~ Dirk
IE doesn't respect the mousedown event on the option tag itself. You've got to use the OnChange event of the select tag, which is not what you (nor I) want. I was trying to do the exact same thing as you and was stopped at every attempt. I finally gave up and made it a list of checkboxes because I can get the same behavior out of mine that you are trying to do here.
You can see this question for some options, but I never did get it to work the way you are describing.

jQuery Show/Hide divs using same class not working because of html.push?

The object is to Show-Hide text located under their respective Titles, so a User reads the title and shows or hides text belonging to that title if the User wants to read more.
I tried whatever I could find so far on here, we're talking dynamically setting text coming from a spreadsheet, can't use IDs, must work with .class, must be missing something, I have this piece of code:
... html.push('<div class="comments">' + comment + '</div></div></div>');
but when I try this Show-Hide code nothing happens, even if the error console shows nothing. Basically I want to Show-Hide the .comments class divs with a show-hide toggle link located under each of them. I say them because the .comments divs are reproduced dynamically while extracting text coming from Google spreadsheet cells/row (one .comments div per spreadsheet row). I tried .next, child and parent but they all divorced me so I dunno looks like a dynamic issue. So far I only managed to globally toggle all divs to a visible or hidden state but I need to toggle independantly individual divs.
I prefer a jQuery solution but whatever worked so far was achieved with native javascript.
Note: If a cross-browser truncate function which would append a more-less link after a number of words (var) in each .comments divs would be easier to implement then I would gladly take that option. Thx for any help, remember I am still learning lol!
I have been working on an entirely JS UI project and have brought myself to using $('', { properties }).appendTo(BaseElement) to work best for adding HTML elements because it appropriately manipulates the DOM every time.
If you are having good luck with push elsewhere, however, breakpointing on the line where you do your $('.class').hide() and see what $('.class').length is. Alternately, you can just add alert($('.class').length) to your code if you are unable to breakpoint the code. If it is 0, then your elements have not been properly added to the DOM. Changing to append will ensure they are part of the DOM and therefore targetable via JQuery.