hey so I have a problem with my HTML script
so first I had this
index.html
<script src="index.js"></script>
<script src="loadplayer.js"></script>
index.js
const script = document.createElement("div")
script.innerHTML = urlvid
const player = document.getElementById("head")
player.appendChild(script)
in the script, there is a function named loadvideoplayer()
loadplayer.js
function loadvideoplayer(title){
let array = {title}
console.log(array)
console.log(array.title.sources[0].file)
console.log("Loaded")
}
the problem is the function on the script tag from index.js is not executed after the is created
how can i make it executed after the created ?
btw the urlvid contain this
loadvideoplayer(
{
title : '',
tracks: [{
file: '',
kind: 'captions',
'default': true
}],
sources: [{'file':'vidurl','type':'video/mp4'}],
image: "imgurl",
captions:
{
color:'#FFFF00',fontSize:17,backgroundOpacity:50
},
}
);
Move your HTML declaration like this:
<!-- import libraries before executing code -->
<script src="loadplayer.js"></script>
<script src="index.js"></script>
Then you can do something like this:
function loadVideoPlayer(title) {
console.log('Loaded Video: ', title);
}
let script = document.createElement('script');
script.innerHTML = 'console.log("Appended script executed!"); myObject = { title: "Wonderful Stack Overflow Answers" };'
document.head.appendChild(script);
loadVideoPlayer(myObject.title)
Obviously you must know in advance what are the variables in the script you are injecting into your page (like myObject in the example). Without knowing the script you are loading you can't use its variables.
Note that as we are using innerHTML and not src in the appended script, you can just trigger the function just after appended the child into the document head.
If you use src, the browser will ask asynchronously the script, so you must do:
I also warn you on the fact that injecting a script into a page is always a security risk, so you must rely on what you are injecting (it is a secure source?).
script.addEventListener('load', function() {
loadVideoPlayer(myObject.title)
});
Side Note: you could also use eval (MDN), many will state that eval is evil, but you are actually ignoring the same security risks by evaluating the code in the script tag:
function loadVideoPlayer(title) {
console.log('Loaded Video: ', title);
}
let script = 'console.log("Appended script executed!"); myObject = { title: "Wonderful Stack Overflow Answers" };'
eval(script);
loadVideoPlayer(myObject.title)
Related
I would like to be able to embed the content that gets created via this snippet anywhere I like, using one line of code - same way that you get any kind of snippet somewhere, so that it renders an iframe or similar in return. I am not sure where to start with that, and if this what I already have is usable/ready to "convert" to an embeddable snippet. I went through a few tutorials but it was quite confusing since it was using some backend stuff I don't really understand...
Obviously, it should be hosted somewhere, but the part where I need to "call" the snippet is not really clear to me. Now, it just appears everywhere on my website since it's just a normal JS file which gets included, same as all other files.
It would be great if I could just pack it somehow and call it like this let's say:
<script src="link-to-my-snippet.js"></script>
If someone could direct me a bit that would be great.
const data = [
{
name: "John Doe",
age: 40
},
{
name: "Jane Doe",
age: 50
}
];
window.addEventListener("DOMContentLoaded", function() {
function Item(configurationObject) {
apiCall(data);
}
function apiCall(data) {
// Do some API call and get back the data
// With the Unique ID that wass passed in via the
// configuration Object
// "data" is faked just for the demonstration
createHTML(data);
}
function createHTML(data) {
const mainDiv = document.createElement("div");
document.body.appendChild(mainDiv);
let html = '';
data.forEach((user) => {
html += `
<div class="test">
<p>${user.name}</p>
<p>${user.age}</p>
</div>
`;
});
mainDiv.innerHTML = html;
createStylesheet();
}
function createStylesheet() {
const style = document.createElement("style");
style.innerHTML = `
.test {
background-color: lightgreen;
color: white;
}
`;
document.head.appendChild(style);
}
let configurationObject = {
uniqueID: 1234
}
let initialize = new Item(configurationObject);
});
There are two ways:
Using modern javascript - ES6, Webpack, SCSS, and then bundle all in a single file using NPM
Follow: https://blog.jenyay.com/building-javascript-widget/
Pure JavaScript - Custom Created.
You can create a self-executable anonymous function like this and write your complete widget code - including your HTML, CSS, etc inside this. It will be executed once your page is loaded with this script.
(function() {
// The following code will be enclosed within an anonymous function
var foo = "Hello World!";
document.write("<p>Inside our anonymous function foo means '" + foo + '".</p>');
})(); // We call our anonymous function immediately
For the second type solution you can also follow following article:
https://gomakethings.com/the-anatomy-of-a-vanilla-javascript-plugin/
I'm assuming that you have some local static HTML/CSS page.
First off, you don't need to render the generated HTML by the javascript in an iframe, almost any element will do. The purpose of JS is to create, manipulate and read DOM-elements, so don't feel limited.
Secondly, some of that code is useless for your purpose, unless you plan on doing stuff with an API (which I assume not), and have an actual need for a unique ID. In that code, that unique Id isn't unique anyway and isn't used for anything.
There is so many ways to implement this script on any page of your choice, but here's one:
You have a HTML-file, in that one, put:
<div id="users-list"></div>
wherever you want the list to appear.
Create a file called whatever you want, but for example users-list.js. Check the demo in my answer for the JS code to put in that file.
In any HTML file where you have added an element with the ID of 'users-list', simply also add the script in that same HTML file. Preferably before the ending tag.
<script src="/path/to/users-list.js"></script>
Of course, you make this in so many ways, and expand on it infinitely. For example, something like this could be cool to have:
<div id="some-div-id"></div>
...
<script src="/path/users-list.js">
getUsers({
element: 'some-div-id'
theme: 'dark',
layout: 'boxes' // or 'rows'
});
</script>
Then you could invoke the script on different pages with different generated HTML, but of course, that would require some modification of your JS code, to actually print out different css content, and getting the right element to place the data in.
In any case, it wouldn't be hard to do.
But back on topic, working demo:
const users = [
{
name: "John Doe",
age: 40
},
{
name: "Jane Doe",
age: 50
}
];
const styles = `
.user {
background-color: lightgreen;
color: white;
}
.age { font-weight: bold; }
`;
function setStyles() {
const styleElement = document.createElement('style');
styleElement.innerHTML = styles;
document.head.appendChild(styleElement);
}
function setUsers(users) {
let element = document.getElementById('users-list')
let usersHtml = '';
users.forEach(user => {
usersHtml += `
<div class="user">
<p class="name">${user.name}</p>
<p class="age">${user.age}</p>
</div>
`;
})
if (element) element.innerHTML = usersHtml;
}
window.addEventListener("DOMContentLoaded", function () {
setUsers(users);
setStyles(styles);
});
<div id="users-list"></div>
Here is an example of a self invoking recursive IIFE checking for the document readyState, better than the accepted answers solution
const myPlugin = () => {
// stuff
}
/**
* Checks the document readyState until it's ready
*/
(ready = (delay) => {
// this is always 'complete' if everything on the page is loaded,
// if you want to check for a state when all html/js is loaded but not all assets, check for 'interactive'
if (document.readyState == 'complete') {
myPlugin() // your stuff being invoked when doc is ready
} else {
console.log('Retrying!')
setTimeout(() => { ready(delay) }, delay)
}
})(50)
I'm interested in using the Monaco editor in a Vue.js backed Electron project.
Thus far:
Microsoft provides an Electron Sample (which I've run and works correctly)
There are a variety of vue.js npm repos for monaco - yet none of them seem to fully support Electron right out of the box.
The one that looks most promising is vue-monaco but I've run into issues correctly integrating it.
AMD Require?
This is the code from the Microsoft sample for using with Electron
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Monaco Editor!</title>
</head>
<body>
<h1>Monaco Editor in Electron!</h1>
<div id="container" style="width:500px;height:300px;border:1px solid #ccc"></div>
</body>
<script>
// Monaco uses a custom amd loader that overrides node's require.
// Keep a reference to node's require so we can restore it after executing the amd loader file.
var nodeRequire = global.require;
</script>
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script>
<script>
// Save Monaco's amd require and restore Node's require
var amdRequire = global.require;
global.require = nodeRequire;
</script>
<script>
// require node modules before loader.js comes in
var path = require('path');
function uriFromPath(_path) {
var pathName = path.resolve(_path).replace(/\\/g, '/');
if (pathName.length > 0 && pathName.charAt(0) !== '/') {
pathName = '/' + pathName;
}
return encodeURI('file://' + pathName);
}
amdRequire.config({
baseUrl: uriFromPath(path.join(__dirname, '../node_modules/monaco-editor/min'))
});
// workaround monaco-css not understanding the environment
self.module = undefined;
// workaround monaco-typescript not understanding the environment
self.process.browser = true;
amdRequire(['vs/editor/editor.main'], function() {
var editor = monaco.editor.create(document.getElementById('container'), {
value: [
'function x() {',
'\tconsole.log("Hello world!");',
'}'
].join('\n'),
language: 'javascript'
});
});
</script>
</html>
The module I'm using allows for something like this:
<template>
<monaco-editor :require="amdRequire" />
</template>
<script>
export default {
methods: {
amdRequire: window.amdRequire
// Or put this in `data`, doesn't really matter I guess
}
}
</script>
I can't seem to figure out how to get the correct amdRequire variable defined in Electon + vue. I believe if i can conquer this everything else becomes simple.
The Electron FAQ mentions something about this (i think): I can not sue jQuery/RequireJS/Meteor/AngularJS in Electron
Sample Code
I put a sample project up on GitHub https://github.com/jeeftor/Vue-Monaco-Electron with the "offending" component being in ./src/renderer/components/Monaco.vue
Summary
How can I get this Monaco Editor to load correctly inside of a Vue.js component that will be run inside electron?
Thanks for any help you can offer.
I'm doing nearly the same, just without the extra vue-monaco component. After struggling quite a bit, I could solve the problem:
function loadMonacoEditor () {
const nodeRequire = global.require
const loaderScript = document.createElement('script')
loaderScript.onload = () => {
const amdRequire = global.require
global.require = nodeRequire
var path = require('path')
function uriFromPath (_path) {
var pathName = path.resolve(_path).replace(/\\/g, '/')
if (pathName.length > 0 && pathName.charAt(0) !== '/') {
pathName = '/' + pathName
}
return encodeURI('file://' + pathName)
}
amdRequire.config({
baseUrl: uriFromPath(path.join(__dirname, '../../../node_modules/monaco-editor/min'))
})
// workaround monaco-css not understanding the environment
self.module = undefined
// workaround monaco-typescript not understanding the environment
self.process.browser = true
amdRequire(['vs/editor/editor.main'], function () {
this.monaco.editor.create(document.getElementById('container'), {
value: [
'function x() {',
'\tconsole.log("Hello world!");',
'}'
].join('\n'),
language: 'javascript'
})
})
}
loaderScript.setAttribute('src', '../node_modules/monaco-editor/min/vs/loader.js')
document.body.appendChild(loaderScript)
}
I've just taken the electron-amd sample and adjusted it a bit. I call the loadMonacoEditor function in the components' created function.
In order to not get the Not allowed to load local resource: file:///C:/.../node_modules/monaco-editor/min/vs/editor/editor.main.css problem, you also have to set
webPreferences: {
webSecurity: false
}
in your instance of the BrowserWindow.
I have a situation where I need to decide to include a html link based on client side boolean value and server side boolean value like this :
const preloadSupported = () => {
const link = document.createElement('link');
const relList = link.relList;
if (!relList || !relList.supports)
return false;
return relList.supports('preload');
};
if (!#Model.oldLayout && preloadSupported())
{
<link rel="preload" href="staticResource.js" as="script" />
}
or
if (#Model.oldLayout) //server side boolean
{
if (preloadSupported()) // client side boolean
{
#foreach (var url in Model.cssUrls)
{
<link rel="preload" href="#Html.StaticFile(url)" as="script"/>
}
}
else
{
#foreach (var url in Model.cssUrls)
{
<link rel="prefetch" href="#Html.StaticFile(url)"/>
}
}
}
how should I do that? I tried different variations none of them worked! thanks for your help in advance
You need to place this code in your razor file inside your javascript tags for the client.
Pass in the urls for the scripts from the server, or hard code it in the javascript code.
<script>
#if (!Model.OldLayout)
{
<text>
if (preloadSupported())
{
loadScript("/scripts/script01.js");
loadScript("/scripts/script02.js");
function loadScript(url)
{
var script = document.createElement('script');
document.head.appendChild(script);
script.onload = function()
{
// Do anything with the script here (because it's now loaded)
};
script.src = url;
}
}
</text>
}
</script>
Mixing server side and client side code can be tricky. You can use rendered server side code with javascript, but it can't really work the other way around.
In your first example, the if-statement would have to be:
if (!('#Model.oldLayout' === 'True') && preloadSupported())
{
//..link
}
The problem here is that the link wouldn't exist until the page was parsed and rendered. You could perhaps use document.write, createElement or jquery $.load() to add it, but that depends on what the external file is used for and when it has to be added.
Best bet would really be to check for "preloadSupport" earlier, or redirect the visitor if preload is supported and create a new response.
I'm creating an HTML element using Polymer, and I want it to be able to work with an ES6 class I've written. Therefore, I need to import the class first and then register the element, which is what I do:
(function() {
System.import('/js/FoobarModel.js').then(function(m) {
window.FoobarModel = m.default;
window.FoobarItem = Polymer({
is: 'foobar-item',
properties: {
model: Object // instanceof FoobarModel === true
},
// ... methods using model and FoobarModel
});
});
})();
And it works well. But now I want to write a test HTML page to display my component with some dummy data:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="/bower_components/webcomponentsjs/webcomponents.js"></script>
<script src="/bower_components/system.js/dist/system.js"></script>
<script>
System.config({
map:{
traceur: '/bower_components/traceur/traceur.min.js'
}
});
</script>
<link rel="import" href="/html/foobar-item.html">
</head>
<body>
<script>
(function() {
var data = window.data = [
{
city: {
name: 'Foobar City'
},
date: new Date('2012-02-25')
}
];
var view;
for (var i = 0; i < data.length; i++) {
view = new FoobarItem();
view.model = data[i];
document.body.appendChild(view);
}
})();
</script>
</body>
</html>
Which isn't working for one simple reason: the code in the <script> tag is executed before Polymer registers the element.
Thus I'd like to know if there's a way to load the ES6 module synchronously using System.js or even better, if it's possible to listen to a JavaScript event for the element registration (something like PolymerElementsRegistered)?
I've tried the following without success:
window.addEventListener('HTMLImportsLoaded', ...)
window.addEventListener('WebComponentsReady', ...)
HTMLImports.whenReady(...)
In the app/scripts/app.js script from the polymer starter kit, they use auto-binding template and dom-change event
// Grab a reference to our auto-binding template
var app = document.querySelector('#app');
// Listen for template bound event to know when bindings
// have resolved and content has been stamped to the page
app.addEventListener('dom-change', function() {
console.log('Our app is ready to rock!');
});
Also check this thread gives alternatives to the polymer-ready event.
The seo company I work closely with told me I needed to add this code inbetween the body tags of my meteor project.
<script type="text/javascript">
/* <![CDATA[ */
var google_conversion_id = 123456789;
var google_custom_params = window.google_tag_params;
var google_remarketing_only = true;
/* ]]> */
</script>
<script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js">
</script>
<noscript>
<div style="display:inline;">
<img height="1" width="1" style="border-style:none;" alt=""src="//googleads.g.doubleclick.net/pagead/viewthroughconversion/949352235 /?value=0&guid=ON&script=0"/>
</div>
</noscript>
However as we know script tags don't get executed properly inside body tags.
So I searched on google to find an answer and I found this code that supposedly works but it's in REACT. How can I convert this react code into normal javascript that I can refer from a template or something. I'm thinking in a onCreated and or onRendered function.
GoogleTag = React.createClass({
displayName : 'GoogleTag',
render(){
var src = '';
if(this.props.type === 'conversion'){
src = _.template('//www.googleadservices.com/pagead/conversion/<%=id%>/?label=<%=label%>&guid=ON&script=0'),
src = src({id : this.props.id, label : this.props.label})
}
if (this.props.type === 'remarketing') {
src = _.template('//googleads.g.doubleclick.net/pagead/viewthroughconversion/<%=id%>/?value=0&guid=ON&script=0'),
src = src({id: this.props.id})
}
var style = {
display : "inline"
},
imgStyle = {
borderStyle : "none"
}
return (
<div style={style}>
<img height="1" width="1" style={imgStyle} alt="" src={src}/>
</div>
)
}
})
You can use Google Remarketing library for async actions and write your meta-data via direct call tracking function:
/* remarketingTrack utility */
export default function remarketingTrack(data = {}) {
try {
trackConversion({
google_conversion_id: SOME_ID,
google_custom_params: data,
google_remarketing_only: true
});
} catch (e) {
// error
}
}
/** somewhere in ReactJS component **/
componentDidMount() {
remarketingTrack({
flight_originid: XXX,
flight_destid: XXX,
flight_startdate: date,
flight_pagetype: 'home',
});
}
I think that it's more flexible and neat solution
Place
<script type="text/javascript">
var google_conversion_id = 123456789;
var google_custom_params = window.google_tag_params;
var google_remarketing_only = true;
</script>
<script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js"></script>
in your head and you will be fine.
In Meteor you can only have one <head> defined in your project, just create a file called head.html on the client and place the code above inside a body tag in the file.
First, remove any code that you have regarding this. A standard implementation won't work with Meteor without a custom written implementation.
Second, take the code block that Google gives you. Throw out all of the JavaScript, and all of the script tags. You don't need them.
We'll be running a 'non-standard implementation', but it work's the same as far as we're concerned. Take the code within the noscript tags (the div with the img tag), and we need to place it in every place our pages render. So, place it in your Blaze or React layout template, and you should be done.
Google will detect the noscript implementation (which they create so it'll work for visitors who don't have JavaScript enabled, but we are hacking it for use with our implementation), all Google really needs to see is the url call from the img tag :)