I have a metro application in which I want to call a javascript function from another .js file? can anyone help me.
Thank you.
All scripts in javascript are merged into a "script context". This means that if you have:
File1.js:
function a() { b(); }
File2.js:
function b() { alert("hi"); }
then as long as file2.js is included before b is called, everything will be fine.
This means in your HTML should have the <script> tags included, and you'll be good.
If you are using WinJS, a better example might be:
File1.js:
WinJS.Namespace.define("MyNamespace", {
firstFunction: function() { MyNamespace.secondFunction(); }
});
File2.js
WinJS.Namespace.define("MyNamespace", {
secondFunction: function() { alert("hi"); }
});
default.html:
<script src="/file1.js"></script>
<script src="/file2.js"></script>
However JavaScript doesn't have a built in dynamic loading of "References". You have to build or use your own.
There are many ways to skin this cat, so I would recommend you look a them and decide which meets your needs.
Require JS
Built in Page controls/fragment loading in WinJS. If you define a page in WinJS, when the html file for that page is loaded, any scripts declared in the html will be brought in automatically. Same is true of raw fragment loading.
You can just the file that contains the definition of the function needs to be referenced before the file which calls the function just like you would do if it was a browser not a Windows 8 app.
In fact not even that much is necessary. If you are calling the function after window.load or document.load then that means that all of your referenced javascript files have loaded already so the reference sequence doesn't even matter.
Related
I have been instructed to assert that our errors have been surfaced in bootstrap-vue toasts. How can I assert that the toast has been made on my tests. I was hoping to mock out ‘this.$bvToast.toast’ however I have been unable to find anything salient so far.
I stumbled upon the same problem and the way I solved it was to wrap the this.$bvToast.toast() around a component method showToast():
// component
{
...
showToast(title: string, content: string) {
this.$bvToast.toast(
content,
{
title,
...
}
}
}
}
Then, in my jest file I just use a spy and make sure the parameters are the ones I expect
// component.spec
const mySpy = jest.spyOn(myComponent, 'showToast');
...
your code here
...
expect(mySpy).toHaveBeenCalledWith(expectedTitle, expectedContent)
Of course, this doesn't test the actual text inside the bootstrap-vue toast component, but this defeats also the purpose of the unit test: you assume that the toast works as it should :)
I am looking for a way to NOT reuse DOM elements within lit-html/lit-element (yes, I know, I'm turning off one of the prime features). The particular scenario is moving an existing system to lit-element/lit-html that at certain points embeds the trumbowyg WYSIWYG editor. This editor attaches itself to a <div> tag made within lit-element and modifies its own internal DOM, but of course lit-html does not know that this has happened, so it will often reuse the same <div> tag instead of creating a new one. I am looking for something similar to the vue.js key attribute (e.g., preventing Vue from aggresively reusing dom-elements)
I feel like the live() directive in lit-html should be useful for this, but that guards against reuse based on a given attribute, and I want to prevent reuse even if all attributes are identical. Thanks!
I have had similar issues with rich text editors and contenteditable - due to how templates update the DOM you don't want that to be part of a template.
You do this by adding a new element with the non-Lit DOM and then adding that to the DOM that Lit does manage:
class TrumbowygEditor
extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({mode: 'open'});
const div = document.createElement('div');
shadow.appendChild(div);
const style = document.createElement('style');
// Add CSS required
shadow.appendChild(style);
$(div).trumbowyg(); //init
}
}
customElements.define('trumbowyg-editor', TrumbowygEditor);
As this is running in a custom element's shadow DOM Lit won't touch it, you can do:
html`
<div>Lit managed DOM</div>
<trumbowyg-editor></trumbowyg-editor>`;
However, you will have to implement properties and events on TrumbowygEditor to add everything you want to pass to or get from the nested jQuery component.
You can add the scripts with import if you can get module versions of jQuery/Trumbowyg (or your build tools support it) or you can add <script> tags to your component, add fallback loading DOM content in the constructor, and then on the load event of the <script> call the $(div).trumbowyg() to init the component.
While messier and more work I'd recommend the latter as both components are large and (thanks to jQuery being built on assumptions that are now 15 years old) need to load synchronously (<script async or <script defer don't work). Especially on slower connections Lit will be ready long before jQuery/Trumbowyg have loaded in, so you want <trumbowyg-editor> to look good (show spinner, layout in the right amount of space etc) while that's happening.
You write that you attach the external library directly to an element managed by lit-html. It sounds like you're doing essentially this:
render(html`<section><div id=target></div></section>`, document.body)
external_lib.render_to(document.querySelector("#target"))
If this is what you do instead try to create your own div, let the external lib render to that div, and finally attach that div to lit-html:
let target_div = document.createElement('div')
render(html`<section>${div}</section>`, document.body)
external_lib.render_to(target_div)
The most up-to-date answer to this problem is to use Lit's built-in keyed directive. This scenario is exactly what it's for:
https://lit.dev/docs/templates/directives/#keyed
Associates a renderable value with a unique key. When the key changes, the previous DOM is removed and disposed before rendering the next value, even if the value—such as a template—is the same.
#customElement('my-element')
class MyElement extends LitElement {
#property()
userId: string = '';
render() {
return html`
<div>
${keyed(this.userId, html`<user-card .userId=${this.userId}></user-card>`)}
</div>`;
}
}
i want to dynamically create DIV Containers via JSInterop in Blazor Webassembly. My approach was to create a CreateElement method in C# which calls createElement in javascript and returns a ElementReference as a Result. But when i run the Following code, i just get an empty object.
C# code:
public object CreateElement(ElementReference elementReference)
{
return JsRuntime.Invoke<object>("createElement",
elementReference,
DotNetObjectReference.Create(this));
}
Javascript code:
createElement(element, objectReference) {
const newDiv = document.createElement("div");
return element.appendChild(newDiv);
}
You don't need JS for that. Blazor was made so you don't have to manipulate the DOM. Create components. Manipulating the DOM this way defeats the purpose for which Blazor was made. You may want to start with some basics at https://learn.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-3.1
As #Porkopek mentioned, there's not really a good reason to do this as it more or less defeats the purpose of using Blazor to dynamically render markup.
If you absolutely have to use createElement, you should bind your JS interop code to the window object to invoke:
window.createDivElement = createElement(element, objectReference) {
const newDiv = document.createElement("div");
return element.appendChild(newDiv);
}
Side note, DotNetObjectReference.Create(this) is for calling back into C# component methods via the [JSInvokable] attribute and probably not needed here.
I am trying to use jQuery Lazy Loading in my Laravel/Vue project but I am struggling to get an image to appear in my Vue component. I have the following img block which I thought would work:
<img v-if="vehicle.photo_path != null" :data-original="'/storage/vehicles/' + vehicle.photo_path" class="lazy" height="180" width="150"/>
I did find this other question on here - Static image src in Vue.js template - however when I try that method I get this: Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead.
So I switched back to the v-bind method but all I am getting is a white box with a grey border - no image. If I v-bind on the src attribute however I can see the image correctly.
I know I have implemented the Lazy Loading plugin correctly as I can successfully call it elsewhere on my site (such as on a blade view), but I'm not sure where I am going wrong. Thank you.
Try moving the call to $("img.lazy").lazyload() into the mounted() method on your Vue instance. I just had a similar issue with Vue and jQuery Lazyload and that solved it for me. For example:
var app = new Vue({
el: ...
data() ...
computed: ...
methods: ...
mounted() {
$("img.lazy").lazyload()
}
})
I found many modules on the internet, but I like to avoid modules when I can. So I came up with something else, I don't know if it's the best, but it works and I didn't see any performances loss, I lazy load all the images when the page loads. You may prefer on scroll if you have lots of them, but I guess you'll figure this out if my answer fits your needs.
You'll need vueX for this, but I'll avoid the set up as this is not replying to your question.
If, like me, you have some kind of Index.vue component which main usage is to initiate all the child components (I use to do that for vue-router for instance), place a mounted() function in it :
mounted(){
const ctx = this;
// You could use this method, but if you reload the page, the cache of the browser won't allow your JS to trigger .onload method, so better use what's after.
/*window.onload = function(){
console.log('page loaded, can load images');
ctx.$store.dispatch('setPageLoaded', true);
}*/
let interval = setInterval(function() {
if(document.readyState === 'complete') {
clearInterval(interval);
ctx.$store.dispatch('setPageLoaded', true);
}
}, 100);
}
=> On the page load, I just set a page_load variable in the store to true.
Then, in any component you'd like to lazy load the image, just use 2 computeds (I used a mixin that I include in my components so I avoid repeating some code) :
computed: {
page_loaded(){
return this.$store.getters.getPageLoaded;
},
image(){
if(this.page_loaded){
console.log('starting loading image');
if(this.product.picture){
return resizedPicture(this.product.picture, this.width, this.height);
}else if(this.product.hasOwnProperty('additional_pictures') && this.product.additional_pictures.length){
return resizedPicture(this.product.additional_pictures[0], this.width, this.height);
}
return '';
}
}
}
page_loaded() goal is to return the store page_loaded variable I talk about.
image() goal is to actually load the image.
I used that for inline CSS background-image property, so my HTML looks like this :
<span v-if="page_loaded" class="image" :style="'background-image:url('+image+')'" :width="1200" :height="900"></span>
I hope it'll help, but as I said, feel free guys to tell me if it's not optimized.
Just like the question title says:
I've got a standard jquery ui tab set. One tab is to another php file, from which i would like to be able to call a function with an argument on the parent page. Can't figure out how to do it.
Code in external page loaded into the tab:
<script language="javascript">
function doSomething(){
parent.dummyfunction("Hello world!");
}
</script>
<input type='button' value='use recipe' onClick='javascript:doSomething()'>
and on the parent, where the tabs are defined, I have:
<script language="javascript">
function dummyfunction(whatever){
alert(whatever);
}
</script>
Thank so much for looking
OK I've figured it out. The jquery ui tabs code loads the external file into the target div as flat html. So instead of needing to call a middle-man function (like the doSomething function in the above example), we just call dummyfunction directly, even though the function is not defined on the external page.