I have a list widget with five rows per page. When the user goes to the next page I reload the page (by doing an unload/load on the data source with the new page number) and that works fine. However, the list stays scrolled to the bottom. How can I scroll the list to the top so the user does not have to?
I tried the ways that work in standard HTML but they do not work in AppMaker, and I cannot find any documentation on how to do this.
Thanks for any tips or pointers.
I realize this is an old post, but for future visitors, here's what worked for me - you need to set the index of the list to zero. App Maker ensures that it scrolls the last selected item into view, and maintains this across navigations.
You can do this by passing in a callback function that runs after loading the list. For me, I reload the list from a dropdown widget that filters the list, so in the onValueChange event I've added:
// Load datasource
widget.datasource.load(function() {
// Set index to 1 to ensure we scroll to top of list
app.datasources.YOURDATASOURCE.selectIndex(0);
});
You can achieve the desired behavior by doing the following:
In the outline, locate the TablePanel widget and select the List:TableBody widget
2.In the property editor, scroll to the Events section and click on the onDataLoad event value. Then click on Custom Action.
Type in this code var elem = widget.getElement(); elem.scrollTop = 0; so that it looks like this
Make sure the change is saved and then preview your app and it should work. Let me know if you need something else or if it don't work.
For me Morfinismo's answer didn't work, but the following did:
In the style editor add CSS for the List element:
.app-pageName-nameOfTheListWidget {
overflow-y: auto;
}
And in the Property Editor under Layout set a Max height.
Related
Question
I'm working with Adobe Scene7 BasicZoomViewer and I'm looking for a way to tell the ZoomViewer to reset the zoom so that the user is no longer zoomed in on an image but instead will show the default "zoom" level.
What I've found
The closest thing I found to what I need is this reset property ZoomView.reset which "Resets the viewport when the frame (image) changes. If set to 0 it preserves the current viewport with the best possible fit while preserving the aspect ratio of the newly set image".
This looks close to something I need but it states that it will reset or preserve the aspect ratio when a new image has been inserted but I am not inserting new images.
Demo from Adobe
There is a button on the image that the API inserts into the page that resets the zoom level. Adobe provides a demo page that shows what I'm working with. If you look at the bottom left, the right-most button is the reset button. When clicked, it has to make some kind of API call and I need to figure out which one it is.
Edit
I've been able to find a minified version of the BasicZoomViewer and I am currently attempting to make sense of the code.
There is an event listener placed on the "Zoom Reset Button" that just simply calls a reset() method on line 274 in the uglified version of the file. Currently, I am trying to make sense of the file and figure out how to access this method.
c.zoomResetButton.addEventListener("click", function () {
c.zoomView.zoomReset()
});
I will be answering my own question. If someone finds a better way please feel free to answer as well.
tldr;
Create a variable to hold the instance of your s7viewers.BasicZoomViewer() and inside of that you can access the event handlers and much more.
Example of calling the reset zoom handler
// instantiate the s7viewers class and save it in a variable
var s7BasicZoomViewer = new s7viewers.BasicZoomViewer({
containerId: 's7viewer',
params: {
asset: assetUrl,
serverurl: serverUrl
})
// example of how to call the "zoomReset()" method
s7BasicZoomViewer.zoomResetButton.component.events.click[0].handler()
Explanation
After digging through the minified code that was uglified I found an event listener on the s7zoomresetbutton DOM class name, or perhaps it's watching for the ID of that DOM element which is the same ID as the container div for your S7 BasicZoom Viewer plus some added text to make this ID unique. For example, if the container div is s7viewer then the reset zoom button will have an ID of s7viewer_zoomresetbutton.
Now, going through the code I found this event listener which let me know there must be some way to call the zoomReset() method.
c.zoomResetButton.addEventListener("click", function () {
c.zoomView.zoomReset()
});
In the code above, the value of c is this or in other words it's the instance of your S7 BasicViewerZoom and in my case I have multiple depending on how many images I need to zoom on.
When instantiating the s7viewers class you can then reference that instance later and access the event handlers on each button and other properties and methods.
From there it was just looking through the object returned from the instance and calling the handler for the reset button.
I'm trying to tweak the WordPress plugin https://github.com/algolia/algoliasearch-wordpress to suit our needs. What we want to be able to do is have a search result that will load the data up in the same page.
I have my WordPress posts and its data being indexed successfully. I have added a search box to the page, and autocomplete is being fired.
Out of the box, the WordPress plugin template wraps the result in an anchor tag and assigns it the URL of the found result. When clicked, this navigates you to that post. However, what I want to do is intercept that click and load the result in the same page without navigating away.
I have removed the href from the anchor. I have also edited the supplied autocomplete.php template where the call to autocomplete:selected occurs. In there I have removed the call to navigate away by removing window.location.href.
Now I have two main issues.
1 - When the user clicks the search result I would like the input to be populate with the title of the item they clicked on. I added this in the autocomplete:selected callback by adding $searchInput[0].value = suggestion.post_title. Which seems to change the value of the input correctly, but as soon as I click away from the input, it is re-set back to the original typed value. So if I type 'may' and click the result 'mayonnaise', the result data can be accessed but the input returns back to 'may'. My function looks this:
/* Instantiate autocomplete.js */
var autocomplete = algoliaAutocomplete($searchInput[0], config, sources)
.on('autocomplete:selected', function (e, suggestion) {
console.log(suggestion);
autocomplete.autocomplete.close();
});
2 - It seems that the autocomplete dropdown does not hide when the user clicks away. To resolve this i've had to use what I think is a bit of a nasty hack with jQuery. I was wondering if this is really required? My code just below the autocomplete:selected call looks like this:
jQuery('body').on("click", function(event){
if (!jQuery(event.target).closest($searchInput[0]).length) {
autocomplete.autocomplete.close();
}
});
Found some answers to my questions.
1 - In order to populate the input with the title of the selected search result I added a call to the setVal method of the autocomplete object. I'[m still not sure why this is required.
/* Instantiate autocomplete.js */
var autocomplete = algoliaAutocomplete($searchInput[0], config, sources)
.on('autocomplete:selected', function (e, suggestion) {
autocomplete.autocomplete.setVal(suggestion.post_title);
});
2 - It looks like the config of the autocomplete object uses the value of WP_DEBUG in order to set the debug value. The options available for the autocomplete component can be found here https://github.com/algolia/autocomplete.js#options. This lead me to find that when debug is set to true, the autocomplete box does not hide on selection. This is to allow for easier debugging and styling of the component.
I have an AppMaker app that has a from based off of one address table/datasource. I can get a form with next/prev buttons, but replaced the key field (name) with a dropdown list of all names (a user can start typing names to jump there, with the dropdown showing).
My hope is that when a user selects from the dropdown, the entire form updates and the next/prev buttons work properly as well (there too many records to page thru with next/prev only). I don't have to have next/prev functionality if it complicates things too much.
Currently the dropdown is working, but I cannot get the index for the next/prev buttons set or the rest of the form to reflect the selected dropdown record.
I've tried to set the "onValueEdit" event to something like this...
var selected = widget.value;
var idx = widget.options.indexOf(selected);
console.log("Selected: "+selected+", index = "+idx+"\n");
if(idx < 0) { //...this error is never hit
console.log("Index error - setting to zero!\n");
idx = 0;
}
widget.datasource.loadPage(idx); //...update form?
Two observations via console logging:
The "idx" var is never set to the selected dropdown index reliably, and is
often "0" (tho no error msg ever shows), so the "indexOf()" function
isn't working as expected.
The "selected" var (name) is always correct.
If I call widget.datasource.loadPage(...) with a fixed value (say 5) it has no effect on what is shows in the form either (previous loaded data remains) - obviously not the way to do it :v/
Can you steer a noob in the right direction?
If you are using default App Maker form, then you can see that so-called pager, doesn't actually paginate. It triggers prevItem/nextItem datasource methods, in other words it navigates through datasource items, not pages. Here is a quote from App Maker docs:
nextItem: Selects the next item. For Query Datasources, if the current item is the last item on the page, then this loads the next page and selects the first item on the newly loaded page.
So, if you already have all your items loaded(you set query page size for your datasource to 0), then you need just to change selected item within datasource:
// onValueEdit dropdown event
// assuming, that form and dropdown share same datasource
widget.datasource.selectKey(newValue._key);
If you really have lots of items and it is not feasible to load all of them in one call... then it will be all another story...
UPDATE:
It's important that Options and Value are set as shown in the image below!
However, I had trouble setting them that way (read: wasted hours!) until I wiped them both completely using More options in the binding picklist, and tried again (I had even tried on a brand new app!). I was being forced to choose ..projections.. and then a final field before the OK button would be available.
Not sure if AppMaker is buggy here or there is something simple I'm not understanding!
None of the coding in my original question is required.
Once set this way, binding just works as you would expect it!!
All other fields are set as #datasource.item. and are bound to whatever item is chosen. No Events settings are necessary for the dropdown either, as I thought they might be.
I deleted this page and started again, and replaced the default business name data field with a drop down, I set the dropdown as:
Options: #datasources.Addresses.items
Value: #datasources.Addresses.item
It works fine?! Not sure what happend in my original page!
UPDATE:
So it seems you need to delete both the Value and Options and then re-enter these. The OK will light up when you do.
Also, my original take on App Maker was to build the UI and attach data. That was my first mistake. You build the data then have App Maker build edit/add pages for you.
I'm trying to customize a survey I'm building on Qualtrics so that certain items in the Table of Contents are disabled. Basically I want you to be able to use the TOC to navigate to previous pages, but not to be able to click on subsequent pages. This is not something I can customize just using the Qualtrics menu.
I'm trying to add Javascript to each block to enable this feature, but can't get it to work. I looked into the html elements on my page and under a div labeled "ToC Sidebar", each element of my ToC is there with a unique id (e.g. "FL_34"), and there's an 'onclick' function under this element to go to link's page. I just want to set this to false. Apologies if this is obvious, I'm new to Qualtrics and Javascript.
Here's what I have right now, any thoughts?
Qualtrics.SurveyEngine.addOnload(function()
{
$("FL_34").onclick = false;
});
That's not the correct way to disable the onclick. What you would do is use: $("FL_34").removeAttribute("onclick");
However, you really don't want to it do that way at all because you don't want to worry about the specific id's, you don't want to display links that don't work, and you don't want to add a script to every page. Instead add this script that hides all the incomplete blocks to the header (Look&Feel/Advanced/Header(edit)/Source):
<script type="text/javascript">
Qualtrics.SurveyEngine.addOnload(function()
{
if($('Toc')) {
$('Toc').select('.Incomplete').invoke('hide');
}
});
</script>
For this to work, you have to set Page Transition to "none".
I've implemented a menu for my asp.net page containing some hyperlinks and loading different contents on their clicks, it's using jquery on behind for it's style mostly and it is working fine. But the problem is, what if a refer to this menu from the outside, i can refer to each of the menu items, i pass parameters on querystring, now i can find which item is clicked but how can i force that hyperlink menu item to be clicked on page load. I'm specifing just their navigation urls, how can i specify that if something is passed in querystring than that specific menu item should be forced clicked on pageload.
Any ideas? Thanks in advance.
The real question lies can you cuase a hyperlink click event?
Now I'm using
Page.ClientScript.RegisterStartupScript(typeof(Page),"test1", "<script>document.getElementById('linkButtonId').click();</script>"); but still nothing desirable happens, seems that this row has no effect at all.
Whether the functionality being executed is client side or server side, it might be a good idea to create a function that will accept the id or something of the menu item being clicked and then handle it appropriately.
Thus all the menu items will call the same function. And since you have the parameters in the query string just pass them through to the function which will handle it accordingly and display the correct content?
You need a bit of separation...
Whatever your click does can be moved into a function, then you can call the function on the click of the menu - but you can also call the function at other times as well.
Before:
<a ... onclick="alert('hello');">Click Me</a>
After:
<a ... onclick="fnSayHello();">Click Me</a>
...
var fnSayHello = function() { alert('hello'); };
fnSayHello();