ressio/lazy-load-xt: "disable auto initialization" seems not working - lazy-loading

It seems to be impossible to disable auto initialization:
Both
$.lazyLoadXT.autoInit=false;
AND
$.extend($.lazyLoadXT, {
autoInit: false
});
do not prevent lazy loading.
jsfiddle:
https://jsfiddle.net/cvlug/16f5h1mn/

You may want to try the code specified in the docs:
$.lazyLoadXT.autoInit=false;
That didn't work for our project, which loads jQuery and lazyLoadXT sandboxed within a Require.js object. LazyLoadXT appears to be trying to access jQuery as window.$ which, but that is not where jQuery is located when it's loaded inside Require.js.
We ended up making a fork of lazyLoad that addresses this issue, by removing their jQuery wrapper and wrapping their code inside a Require.js define statement. Now it's all the same scope. Maybe it will be useful:
https://github.com/Sitetheory/lazy-load-xt

Related

Blazor component - inline styling

I've created a simple blazor app that has a slider on top. There is a javascript self executing function that adds some inline css to this slider so it makes its' height the same as window.height.
I'm adding this javascript file in _Host.cshtml, before closing the body tag.
My issue is that this inline styling isn't applied. I've debugged the javascript code and it gets the correct height, the element on which I want to add the styling is found, the element.css('height', myHeight) is being called with the correct value, but in the end there is no style attribute on that element. I've also tried, after the component has been rendered, to remove the script tag from the page and add it again, hoping that it will re-run and then change the height, but no success there as well.
I've created a .NET Core WebApp using that same slider and everything works as expected (I have the style attribute on my element). In this second app I add the script before closing the body tag, in _Layout.cshtml.
Seems preety much the same as the blazor app, but for some reason, on that one doesn't work.
Do you guys have any idea why?
EDIT:
I've found something interesting. In the beginning, the page is loaded correctly, but the component is being reloaded after the app connects to the we socket Information: WebSocket connected to wss://localhost:44361/_blazor?id=cepYgPnJYddq2bHSywwwYw.. This is when I lose the inline styles.
So how can I stop it from reloading? I guess this is the question.

Server Side Rendering Vue with ASP.NET Core 2

I'm trying to understand the usage and limitations of server side rendering with vuejs when using aspnet core.
I used this starter kit for aspnet core and vuejs to setup a simple vue site, which is running based on the code here: https://github.com/selaromdotnet/aspnet-vue-ssr-test/tree/master
I then modified the project to update the aspnet-prerendering and added vue-server-renderer, compiling a hodgepodge of sources to cobble together this update: https://github.com/selaromdotnet/aspnet-vue-ssr-test/tree/ssr
If I run this project, the site appears to load fine, and if I turn off the javascript in the browser, I can see that it does appear that the server-side rendering executed and populated the html result:
however, because JavaScript is disabled, the content isn't moved into the dom as it looks like it is trying to...
My understanding of server-side rendering is that it would populate the html entirely and serve a completed page to the user, so that even if JS was disabled, they'd at least be able to see the page (specifically for SEO purposes). Am I incorrect?
Now I believe modern search engines will execute simple scripts like this to get the content, but I still don't want a blank page rendered if js is disabled...
Is this a limitation of server-side rendering, or perhaps specifically ssr with vue and/or aspnet core?
or am I just missing a step somewhere?
Edit: more information
I looked at the source code for what I believe is the method that prerenders the section here: https://github.com/aspnet/JavaScriptServices/blob/dev/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs
The line
output.Content.SetHtmlContent(result.Html);
has a null value for result.Html. However, when I manually edit this value to put a test value, it also doesn't render to the output html, and the app div tag is still empty...
If I'm doing something wrong to populate the result.Html value with the expected output, that's one thing, and I would appreciate some help in doing that, especially since the output html appears to be found, since it's in the script that immediately follows...
However, even if I were to populate it, it appears it's being skipped, as evidenced by me manually changing the value. is this a bug in the code or am I doing somethigng wrong, or perhaps both?
As you correctly noticed, for your project, result.Html inside the tag helper is null. So that line cannot be the location where the output is being generated. Since the HTML output from your prerendering script also does not include a script tag, it is clear that something has to generate that. The only other line that could possible do this is the following from the PrerenderTagHelper:
output.PostElement.SetHtmlContent($"<script>{globalsScript}</script>");
That would fit the observed output, so we should figure out where the globalsScript comes from.
If you look at the PrerenderTagHelper implementation, you can see that it will call Prerenderer.RenderToString which returns a RenderToStringResult. This result object is deserialized from JSON after calling your Node script.
So there are two properties of interest here: Html, and Globals. The former is responsible for containing the HTML output that finally gets rendered inside the tag helper. The latter is a JSON object containing additional global variables that should be set for the client side. These are what will be rendered inside that script tag.
If you look at the rendered HTML from your project, you can see that there are two globals: window.html and window.__INITIAL_STATE__. So these two are set somewhere in your code, although html shouldn’t be a global.
The culprit is the renderOnServer.js file:
vue_renderer.renderToString(context, (err, _html) => {
if (err) { reject(err.message) }
resolve({
globals: {
html: _html,
__INITIAL_STATE__: context.state
}
})
})
As you can see, this will resolve the result containing just a globals object with both html and __INITIAL_STATE__ properties. That’s what gets rendered inside of the script tag.
But what you want to do instead is have html not as part of globals but on the layer above, so that it gets deserialized into the RenderToStringResult.Html property:
resolve({
html: _html,
globals: {
__INITIAL_STATE__: context.state
}
})
If you do it like that, your project will properly perform server-side rendering, without requiring JavaScript for the initial view.

Dojo Builds...? What now?

A while back, I looked into a solution for the "flash of unstyled content" when using Dojo and Dojo themes. Someone suggested to combine everything by creating a build, and it'll reduce the load/parse time and remove the need to use preloader overlays, etc.
However, it seems like Dojo is severely lacking in straightforward, "real world" useage examples and tutorials for a lot of its functionality, this especially. A lot of the resources tell you how to set up a build, but not how to implement it.
Let's say I have this in "pageinit.js":
require([
'dojo/parser',
'dojo/dom',
'dojo/dom-class',
//etc...
'dijit/form/ValidationTextBox',
'dijit/form/CheckBox',
// etc...
// Dom Ready call
'dojo/domReady!']
function(
Parser,
Dom,
Class,
// etc...){
// do stuff with parser, dijits, so on.
}
)
Some of the require calls were removed for brevity, but there's a handful of dom requires, style classes, some dijits, etc. When this page loads, there's the flash of unstyled content and then it's fine.
Using the Dojo Web Builder, I selected the modules I'm using, and ran it. It downloaded a zip with a lot of files under it, including a new dojo.js and custom_layer.js.
So my question is now, how do I use these new combined and minified files in place of my "non-build" version? What do I require? Or do I?
So confused...
First, let's understand how the AMD(require/define) API works.
require([
'dojo/parser',
'dojo/dom',
'dojo/dom-class'
], function(parser, dom, domClass){
});
This is going to call the require function, specifying that I need three modules in order to do some work. require will get each module. If will determine if the module has been loaded. If it hasn't it will asynchronously get the file, and load the module into the javascript runtime. Once require has retrieved all of your required modules, it will execute your callback (the function) passing the modules as arguments to the function.
Next, let's understand the build. The dojo build does exactly what you describe. It will compress a bunch of the individual files into a single file. this will make the page load quicker and prevent that 'flash' that you describe.
Finally, putting it all together, you should include the custom_layer.js file along with the dojo.js file.
<script type="text/javascript" src="path/to/dojo/dojo.js" />
<script type="text/javascript" src="path/to/custom_layer.js" />
The web browser will load these two files and evaluate the code. Instead of lazily loading each module in it's own file, the module will already be loaded because it was defined in the custom_layer.js.
So, the answer to your final question is that you should NOT change any of your code based on the specific version of code (source vs custom build) that you are using. Using the AMD api, it should just work.
Not sure if it's best practice or not, but I was seeing the flash of unstyled content when I first started (a few days ago), and saw several examples somewhere that takes care of by just hiding the <body>. Parse will unhide it when it's ready to show something.
<body style="visibility: hidden;">

Jquery with other libraries

I am getting an error message as element.dispatchEvent is not a function. I am using jQuery with prototype in rails 3 application. In my layout file, I have added the js files as below
javascript_include_tag 'jquery','jquery_ujs','prototype','shadowbox/shadowbox.js'
<script type="text/javascript">jQuery.noConflict();</script>
I have also added jQuery.noConflict as above and used jQuery instead of $ in jQuery functions. Any idea how to resolve this.?
In my another controller page action I have also mentioned the same thing as there are some js files which needs to be reloaded only for that particular page.
I am a newbie in js as well as rails also.
you should use jQuery.noConflict right after src to the jQuery library
Using jQuery.noConflict(); should be enough. Please check the code of the page in your browser so you can see when prototype is actually added.
You should have jQuery, then the .noConflict call, then prototype.
Besides adding the 'no conflict' method, I do this instead (though both would probably be best):
I'll 'preset' my custom script page. Let's say my prediction is that I will use maybe 5 blocks of code in a page - this is how I preset my page:
jQuery(document).ready(function($) {
// use $ in here like normal!
});
jQuery(document).ready(function($) {
});
jQuery(document).ready(function($) {
});
jQuery(document).ready(function($) {
});
etc. etc.
Notice this uses the jQuery object itself to pass as the callback function to the .ready method so you can once again use the $ identifier within the functions. I can rename it so their will never be a conflict, and I can use the $ identifier within the function like I normally would. Hope that helps.

Dojo and unregistering widgets

I am new to the Dojo Toolkit. I'm getting the error
Tried to register widget with id=myButton but that id is already registered
whenever I try to load dojo content twice (meaning I load HTML content through jQuery.Load into a container div). Is there a way of unregistering already registered widgets in dojo? I've seen some examples, but I don't really get them working.
My button:
<button dojoType="dijit.form.Button" id="myButton">button</button>
If you're looking to unregister specific widgets, you can use their destroy() or destroyRecursive() methods. The second one destroys any widgets inside the one you are destroying (i.e. calling destroyRecursive on a form widget will also destroy all the form components).
In your case, it sounds like your best bet would be to do this before jQuery.load -
var widgets = dijit.findWidgets(<containerDiv>);
dojo.forEach(widgets, function(w) {
w.destroyRecursive(true);
});
The above code will unregister all widgets in <containerDiv>, and preserve their associated DOM Nodes. To destroy the DOM nodes, pass false to destroyRecursive instead.
Reference:
http://dojotoolkit.org/api/1.3/dijit/_Widget/destroyRecursive
Based on http://bugs.dojotoolkit.org/ticket/5438, I found a sufficient way of destroying dojo-widgets:
dijit.registry.forEach(function(w){
w.destroy();
});
This worked for me:
dijit.byId( 'myButton' ).destroy( true );
I think you would be better off removing the id from your button and accessing it using an attach point. You would basically do <button dojoType="dijit.form.Button" data-dojo-attach-point="myButton">button</button>
then in your code you would access it like this.myButton.... however im not sure which version of dojo you are using. This will fix any id issues since dojo will assign a unique id to it automatically.