Blazor - Navigate to Id after page renders - javascript

Framework: .Net6.0
C#: 10.0
How do I navigate to an Id after the page finishes rendering? I have a virtualized list of items, one item out of the list gets assigned an Id.
I want to be able to scroll down to this Id after the page finishes rendering.
I'm able to scroll down 'manually' simply by adding '#IdName' to the end of the url. I'm unable to get blazor to scroll down to this Id using the Navigation Manager.
I've tried the following in OnAfterRenderAsync:
_navigationManager.NavigateTo("/test#testscroll");
and the following JS and C# code in OnAfterRenderAsync
await JsRuntime.InvokeVoidAsync("scrollToElementId", "");
Javascript
scrollToElementId = (elementId) => {
elementId = "testscroll";
console.info('scrolling to element', elementId);
var element = document.getElementById(elementId);
if(!element)
{
console.warn('element was not found', elementId);
return false;
}
element.scrollIntoView();
return true;
}
The JS file has been added to wwwroot/Javascript/main.js
and
<script src="Javascript/main.js"></script>
added above
<script src="_framework/blazor.server.js"></script>
in _Layout.cshtml
The JS listed above DOES work, but only for items that are not in the virtualized list. If I add a static div to the bottom of the list, out side the Virtualize tag, it will scroll to the bottom. But if I try to use a Id from and item inside the Virtualize tag, it does not scroll.
I receive the element was not found console warning from the JS, when using Id's from the virtualized list.

Related

How to autoscroll with Javascript a Class of ReactJS project

I have a web page that I want scroll automatically but the webpage is in reactjs. It has a classname called "ReactVirtualized__Grid__innerScrollContainer", I just want create a script for scroll down automatically but it doesn't work!
I will put my code:
function autoScrolling(){
var element = document.getElementsByClassName("ReactVirtualized__Grid__innerScrollContainer")[0];
element.scrollTo(0, 1000);
//window.scrollTo(0, element.scrollHeight);
}
autoScrolling();
But it only prints a number but doesn't do nothing... I tried a lot of things but nothing works...
Thanks!

Does JavaScript have any functionality for building URLs?

I have an index view of cards (e.g. playing cards) laid out in a BootStrap grid. Each card is in a div, and I have a jQuery click handler for each div, to open a details page for any card (card div) that is clicked. So the redirect from the index to detail view is all accomplished using this (rather smelly) JavaScript:
var showDetail = function (index) {
const newUrl = "#($"http://{Model.HostName}{Url.Action("Details", "Card")}/")" + index;
window.location = newUrl;
};
I don't like to depend on the Razor code nugget to give me the hostname and the url's path. Does JavaScript have any functionality that I can use to achieve the same as the above dodgy code?
You can create create an anchor on the fly and read its href property.
console.log($('<a>', {
"href": '/test/for/relative/url'
}).prop('href'))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
And, Also URL API can be used.

multiple instanced dynamic javascript popup link

I realize that this posting is possibly a repeat of this one:
Using Javascript to dynamically create links that trigger popup windows
But I'm not good enough at JavaScript to understand how to apply it to the context in which I'm trying to do it.
I'm creating a javascript snippet that could possibly be called multiple times from within a CMS (Umbraco ) that generates webpages.
An id (variable name: mediaid) is passed into this context and I want to dynamically create a link that has an onclick event to launch a popup. I take the ID passed into the context I'm working in (Umbraco calls them "macros") and append the id as a query string to a different URL (same domain) so that the resultant page can do some stuff with the id.
What I have works, but only for one instance on a page. I need a user to be able to insert multiple dynamic links on a page. Right now, the last link generated uses the onclick event for all instances on the page.
<script>
var linkWithQueryParam = 'http://www.mydomain.org/test2?yourkey=<xsl:value-of select="$mediaid" />';
var element = document.createElement("a");
element.id = '<xsl:value-of select="$mediaid" />';
element.href = '#';
element.onclick = function() {
setLink(linkWithQueryParam);
}
function setLink(value) {
window.open(value, 'player', 'width=775,height=520,location=0,directories=0,status=0,menubar=0');
}
document.body.appendChild(element);
element.appendChild(document.createTextNode('Listen To This Audio'));
</script>
So, for example, I have a template elsewhere, that calls this macro I created, twice:
<umbraco:Macro mediaid="4107" Alias="audioPlayerPopUp" runat="server"></umbraco:Macro>
<umbraco:Macro mediaid="26502" Alias="audioPlayerPopUp" runat="server"></umbraco:Macro>
The links are generated, but when I click on them, the link generated above in "linkWithQueryParam" is always whatever the last one was, for all links.
I thought maybe if I set the "id" attribute of the link to make it unique, it would work. But that doesn't work. How can I make the dynamically generated onclick event unique?
I ended up changing my approach and using an event delegate per unclenorton's response in this s.o. post
http://davidwalsh.name/event-delegate
I used a variation on the example to only disable the default link behavior, first checking to see that the link class is matched. This script relies on a named div that is available sitewide and is placed at the bottom of a master template so it is available:
<script>
document.getElementById("main").addEventListener("click", function(e) {
if(e.target)
{
if(e.target.nodeName == "A")
{
if(e.target.className == "miniplayer")
{
if(e.preventDefault) {
e.preventDefault();
}
else
{
e.returnValue = false;
}
var target = e.target;
var popupWindows = window.open(target.href, 'player', 'width=775,height=520,location=0,directories=0,status=0,menubar=0');
}
}
}
});
</script>
I then edited my user macro to simply place the class "miniplayer" on each link it creates and include the media id as a query parameter to another url which provides the media player. That other url resource then pulls the query param id out of the url and looks up the link to the media item. But the .js above launches the pop-up the way that I want.
One challenge I had was on how to dynamically assign the resultant media resource to the player (in this case, jPlayer). I found that if I write the media url to a hidden div, I can then just tell the jPlayer to read the value from it.
So I have a second macro which gets the query param and writes it to a hidden div:
<div style="display:none" id="audioUrl"><xsl:copy-of select="$mediaNode/audioUrl" /></div>
Finally, I adjust the jPlayer jQuery to read the url from the hidden div:
$(this).jPlayer('setMedia', {mp3: $("#audioUrl").text() }).jPlayer("play");
It doesn't seem like the best solution. I don't like passing the mediaid through the url, but it fulfills all my other requirements
The issue here is with globals and closures. The linkWithQueryParam variable is a global that is updated each time that script is added. When you click on the link it goes and fetches the url from the variable which is of course the last one.
You can fix this a few ways,
Wrap this code in an immediate anonymous function. This will reduce the scope of the variables to within the anonymous function.
Set the URL when the script is run instead of when the link is clicked.

casperjs: how do I click a remote div and then update it's class name?

As a way of learning CasperJS, I am trying to initiate a click event on a div on a remote page, and then change the class name of the div after I have clicked it. The idea is to find the first clickable div, click it, and then mark it as clicked so I can skip over it to other clickable divs. The markup for the div tag on the remote page looks like:
<div class='clickable_div'></div>
I have tried the following casperjs code:
...
casper.then(function() {
if( this.exists( 'div.clickable_div' ) ) {
this.evaluate(function() {
this.click(document.querySelector('div.clickable_div'));
return document.querySelector('div.clickable_div').setAttribute("className","clicked");
});
}
});
...
It doesn't seem to work. First, I don't think I am initiating the mouse click event on the div correctly. What am I missing? Second, when I fetch the updated html, I don't see any changes in the div's class name. Am I going about this step in the wrong way?
You're calling this.click within evaluate(), it just can't work as evaluate() executes code within the page DOM context where there's probably no window.click method.
Here's a possibly working script:
var linkSelector = 'div.clickable_div';
casper.then(function() {
if (!this.exists(linkSelector)) return;
this.click(linkSelector);
this.evaluate(function(linkSelector) {
__utils__.findOne(linkSelector).setAttribute("className", "clicked");
}, linkSelector);
});
You may want to have better handling of errors and edge cases, but you get the idea.

Execute script after loaded in div [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Initialize script
I have a page (Page1.html) and in this page a div (#div1) that get its content from other divs in another page (Page2 #div1/2/3/4/5). The content is loaded in by jQuery load script. The content is loaded in based on choice in a select box, so the content is loaded in after Page1 has finish loaded.
Problem:
When I get some content from Page2 that's depending on jQuery, these elements don't work. They don't execute.
My questions:
Is there any way to make the a whole inloaded #div from Page2 (all the content) to execute WHEN its loaded in? Right now the existing elements "initialize" when they are loaded in, for example: function initializeSlider(){ slider };.
Now I am trying to add in some more elements depending on jQuery, and wounder if initializing all the objects is the correct way of execute all these scripts, or is there any way that execute all the jQuery elements at once so no need to initializing all object one by one?
Executing or Initializing one script:
If there is no way to execute/initialize all scripts at once when a div is loaded in. I am trying to execute or initialize this script without success, have tried both the "$(document).ready(function() {" and initialize it similar to the slider but the element is not executing.
$(document).ready(function() {
$(".lil").click(function () {
$(this).toggleClass("highlight");
});
});
Depending on what you're initializing; for events make sure and use .on():
$("#div1").on('click', '.lil', function () {
$(this).toggleClass("highlight");
});
Use:
$(document).ready(function() {
$("#div1").on('click', '.lil', function () {
$(this).toggleClass("highlight");
});
});
You could give that function a name. Something like:
function toggleClasses(classToToggle) {
$(classToToggle).click(function () {
$(this).toggleClass("highlight");
});
}
Then, your main page could have:
$(document).ready(function() {
toggleClasses('.lil');
});
And at the bottom of the partial view that you load from page 2, add this:
<script>
toggleClasses('.partialViewClass');
</script>
That way, as soon as that Partial View is done loading, it will call that same function.
If all you're doing is toggling that class, you might want to add a parameter for a secondary class to differentiate the elements in the partial view from the elements in the original page, that way the ones in the original page won't get toggled back when the partial view gets loaded.
So the ones in your partial view would need the highlight class as well as that secondary differentiation class (class="lil partialViewClass"). Pass the class as the parameter to the function so each one will only toggle what it should.

Categories

Resources