How to run scripts in Durandal View - durandal

I have a Durandal App.
On one of the pages, I need to using some existing javascript which I do not want to modify.
However, if I use something like this in the view.html:
<script>alert("test");</script>
the alert is not triggered.
Normally such code would go into the ViewModel. However, in this case, I want to use a Sound Recorder and there is a number of scripts that make this up and I would like to use them as is.
In other words, I would like view.html to act like a regular html page.
When I modify the router to use *.html, it throws an error.
{ route: 'recorder', moduleId: 'views/recorder.html', nav: true }
Is there a way to resolve this?

Taking the recommendation from the OP and posting my comment as an answer:
According to Rob Eiserberg (the author of Durandal), don't do this. The reason being is that all script tags within the view are stripped. I'm sure this is done as a security precaution. Additionally, you could implement the solution recommended here.

Related

Refresh button in React-admin

I'm trying to access the refresh button in react-admin project. I tried using getElementsbyClassName it returns HTMLComponents Object but it isn't accessible i.e I can see the component on printing it to console but isn't accessible by code. Is there a way for me to disable this refresh button wherever I want?
I'm not sure the exact use case here, but you can create your own custom AppBar that renders essentially whatever you want: https://marmelab.com/react-admin/Theming.html#replacing-the-appbar.
also see this GitHub issue that mentions removing it entirely: https://github.com/marmelab/react-admin/issues/3383
Within your custom AppBar you could have some logic checks within your custom AppBar if you know ahead of time when you'll want it disabled (like on a certain page/component).
If you need it to be more dyanimcally disabled, you could probably have a very high-level context/state to control that as well..
**NOTE: I have built a custom AppBar before, but I haven't done any selective rendering or disabling within it. So, I can't guarantee that this is exactly correct, but it fits with other custom components I've built.

Nested Nuxt instances

Not really a code problem more a discussion/brainstroming-post.
I would like to build some light CMS in Vue/Nuxt, which will output a static website in the end.
So I thought about going for one Nuxt-page (does not have to be a Nuxt-page necessarily) containing all the CMS-related stuff and handle the actual website inside a nuxt-child component to keep code tidy.
Problem is, that i can not access the inner Nuxt page, so any editing will be impossible (I want to achieve some simple inline-editing).
For visualization the editor of webflow may be helpful (Directlink to the video). What i want to achieve is a similar version. I would like to have the page separated from the CMS. The CMS would be the lower bottom-bar and provide stuff like the editor for the inline-editing.
Currently my best solution was to define the editing directly inside the page, which is working, but needs to be stripped out for production and makes a future separation impossible.
Is there any solution for this? Or am I thinking the wrong way?
Can I link both instances with a common vuex-store?
You could created two seperate components, one for editing and one for rendering.
These could utilize components themselves to keep the overhead to a minimun.
You could also use the same component, but lazy load the editor features based on some condition like:
If youre fine with having the Editor only available during development you can create an env variable and check for process.env.NODE_ENV !== 'production'
Another way would be to have some sort of authorization that combined with v-if would show the editor or hide it.

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.

Is it possible to use browser->drag() from dusk with Vuedraggable?

We are using VueDraggable (and Vue) in our front-end and we are testing our front-end with Dusk.
I am currently trying to use $browser->drag('selector', 'selector') from dusk to drag objects from one list to the other, but I don't see anything happening during the test (although it might be the action is not visible) nor is the right result shown, the object does not end up in the indicated list.
I was wondering if anybody made a working example already of using $browser->drag() combined with Vue.draggable? I am asking since I don't know if I am trying the impossible or not.
There is an open issue for this on Dusk's Github. I had to open a new issue that can be found here since the original was closed for comment. The link contains a more thorough explanation, but the short answer and solution are highlighted here:
Problem: Laravel's Dusk does not trigger Vue.draggable events. To simulate a drag-and-drop Dusk does a "mouse down", "move mouse to location", and "mouse up" sequence. In theory this is correct but does not trigger Vue' s events.
Solution: Dusk's method does trigger mouse down and mouse up events, so we can simply use those events to trigger the ones desired.
$("a[draggable='true']").on("mousedown", function(event) {
$(this).trigger("dragstart");
});
$("div[droppable='true']").on("mouseup", function(event) {
$(this).trigger("drop");
});
This JSFiddle is an example of how it would work (though you need to implement it on a Laravel project to truly test, of course!).

PhantomJS: injecting a script before any other scripts run

Using PhantomJS, I'd like to inject some JS as if there was an extra <script> tag before any other <script> tags. This is because the scripts on the page use some functions that PhantomJS does not have, namely Function.prototype.bind and window.webkitRequestAnimationFrame. I have a JS file with custom implementations of the two and I'd like PhantomJS to use them when running the scripts on the page.
The difficulty is that if I do page.injectJs before page.open, the script is injected into an empty page and is not carried over to the page being opened.
Alternatively, if I do page.injectJs after page.open, it's too late as the JavaScript errors (undefined functions) have already occurred.
I've found a way that appears to work, but is obviously a hack:
page.onResourceReceived = function() {
page.injectJs('phantom-hacks.js')
};
This injects it many times (twice for each resource, apparently), but that's okay because my script is idempotent. However, I'd like to know the proper way to do this: inject it only once and before any scripts on the page are run.
Thanks :)
I don't think there's a "proper" way to inject such script other than hooking to events.
I've spent half a year working massively with PhantomJs and found no way to inject before all the errors start happening but after the page finished loading.
I would try to go through onInitialized, onLoadStarted, onLoadFinished. Inside the hooks I would call to page.evaluate() which would just modify DOM to have this extra whatever place you like.
I think one of them (the hooks) should give you the right timing you want.
Cheers