how to inject javascript function code along with html code? - javascript

let hideText = () => {
let selection = window.getSelection();
console.log(selection.toString())
if (selection.toString() === "") {
console.log("Selection Error");
} else {
console.assert(selection.focusNode == selection.anchorNode);
let selectionText = selection.toString();
let selectionNode = selection.anchorNode.parentElement;
selectionNode.innerHTML = selectionNode.innerHTML.replace(selectionText,
`
<textarea>${selectionText}</textarea>
<button onclick="count(1)">+</button>
<button onclick="count(-1)">-</button>`
);
}
so above functions run when a user presses a dblctrl, but as shown in last two lines, i have count() to be run, which i have defined in the tool script. if i inject this code into any webpage and press the button, then count function doesnt run, because it is defined in my script not on the webpage, so how can i push my count() along with this html code written in strings to the webpage.
function count(num, selectionNode){
click+=num;
fontsz = parseFloat((fontsz))+(num*0.5)+"em";
document.querySelector("span").style.fontSize=fontsz;
}```
this is my count function.

You can add scripts to a page.
const script = document.createElement('script')
script.src = "https://example.com" // load your script
// or script.appendChild(document.createTextNode(oldButton.innerHTML))
document.body.appendChild(script)
Just mentioning that injecting javascript into other people's sites is unethical and in some cases criminal, you should only be doing this if you own those sites or have permission to do so.

Related

Inject and Execute javascript into iframe

I am getting a string of HTML from an api and I need to pass that into an iframe on my page. While doing that, I also need to inject some javascript code to the head and body of the iframe.
I've been able to successfully do this by the following. I am using React here, but it shouldn't make a difference...
return (
<iframe id="iframe" />
)
React.useEffect(() => {
let template = "<html><head></head><body><div id="content">hello world</div></body></html>"
//really this is my response from an api call so it's a huge string of a complete HTML page
drawTemplateWindow(template)
})
And this is where things aren't working...
const drawTemplateWindow = (string) => {
let iframe = document.getElementById('iframe');
let head = iframe.contentWindow.document.getElementsByTagName('head');
let body = iframe.contentWindow.document.getElementsByTagName('body');
let externalScripts = document.createElement('script');
let editorScript = document.createElement('script');
// set iframe content from template
iframe.contentWindow.document.write(string)
// add external EditorJS Script
externalScripts.src = 'https://cdn.jsdelivr.net/npm/#editorjs/editorjs#latest'
// add externalScripts to head
head[0].appendChild(externalScripts)
if (document.readyState === "complete" || document.readyState === "loaded") {
console.log('have we loaded yet?')
editorScript.type = 'text/javascript';
editorScript.text = `
// EditorJS should be defined in externalScripts include above
let editor = new EditorJS('content')
`
}
// add editor script to end of body
body[0].appendChild(editorScript);
}
I see the externalScript being appended to the Head, and the editor scripts being appended to the end of the body. I can also see my console log that the frame has loaded completely.
I am getting an error that EditorJS isn't defined, or any script I throw in. I've tried to create a local script with an alert function and pass that but it too fails and says that function is undefined.
What am I doing wrong here?

VueJS: How to dynamically execute Javascript from string?

I'm writing a website using VueJS which allows (selected) users to add scripts that are automatically executed upon page load. Here's a sample text that a user might upload:
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.0.5/howler.js"></script>
<script>
var sound = new howler.Howl({
src: ['./sample.mp3']
)}.play();
</script>
This text is stored into a string after retrieving from API backend. The problem now is: I couldn't get it to execute however I try. Is there an option in VueJS that can automatically execute javascripts in strings?
As a reference, here's my code:
var temp_arr = utils.preprocess(vm.chapterInfo.Content)
vm.display = temp_arr[0]
vm.control_script = console.log(temp_arr[1])
// None of below worked
eval(vm.control_script)
document.getElementsByTagName("head")[0].appendChild(control_script)
The problem isn't a Vue one, but a JavaScript one.
I assume that you already understand the security implications of allowing users to run JavaScript; it's rarely a good idea. Sites like JSFiddle do it successfully, however it will take a lot of work and understanding to make it safe, so if you're not 100% sure with what you are doing, then as #WaldemarIce said, you shouldn't do it!
Right, with the warning out the way, you need to do a few things to get this to work:
1) Load the external scripts:
loadScripts() {
return new Promise(resolve => {
let scriptEl = document.createElement("script");
scriptEl.src = "https://cdnjs.cloudflare.com/ajax/libs/howler/2.0.5/howler.js";
scriptEl.type = "text/javascript";
// Attach script to head
document.getElementsByTagName("head")[0].appendChild(scriptEl);
// Wait for tag to load before promise is resolved
scriptEl.addEventListener('load',() => {
resolve();
});
});
}
Here I'm simply attaching the external script to the head of the document and attaching a load event, which resolves the Promise when loaded.
2) Now we have loaded the external script we can execute the remainder of the script. You will need to strip out the script tags, so you can do something like this:
executeScript() {
// remove script tags from string (this has been declared globally)
let script = string.replace(/<\/?script>/g,"")
eval(script)
}
Form the Vue perspective, you can then execute this inside the created hook:
created() {
this.loadScripts().then(() => {
this.executeScript();
});
},
I'll leave it to you to extract the external scripts you want to load from your user input, but here's a JSFiddle: https://jsfiddle.net/49dq563d/
I recently came across this problem and had to extend on the answer from #craig_h. The example below allows full embed code to be sent through as string (HTML elements as well as scripts and inline JS). This is using DOMParser.
<div ref="htmlDump"></div>
<script>
import Vue from "vue";
export default {
...
methods: {
cloneAttributes(element, sourceNode) {
let attr;
let attributes = Array.prototype.slice.call(sourceNode.attributes);
while(attr = attributes.pop()) {
element.setAttribute(attr.nodeName, attr.nodeValue);
}
}
},
mounted(){
if(this.embedString && this.embedString.length > 0)
{
//Parse the code given from the API into a new DOM so we can easily manipulate it
var parser = new DOMParser();
var htmlDoc = parser.parseFromString(this.embedString, 'text/html');
//Get the contents of the new DOM body and loop through.
//We want to add all HTML elements to the page and run / load all JS
var kids = [...htmlDoc.body.children];
let len = kids.length;
for (var i = 0; i < len; i++) {
var item = kids[i];
if(item.tagName == "SCRIPT")
{
//If we have a 'src' attribute then we're loading in a script
if(item.hasAttribute('src'))
{
//Create a new element within the current doc to trigger the script load
let scriptEl = document.createElement("script");
//Copy all attributes from the source element to the new one
this.cloneAttributes(scriptEl, item);
//Attach script to the DOM to trigger it to load
this.$refs.htmlDump.appendChild(scriptEl);
} else {
//if we don't have a 'src' attribute then we have some code to run
eval(item.innerText);
}
} else{
this.$refs.htmlDump.appendChild(item);
}
}
}
}
...
}
</script>

where is showing conversation value

THis topic is abouton google add word (conversation)
Below is my conversation setup screenshot
http://nimb.ws/alycTQ
Below is my code that was putted on body tag
<script type="text/javascript">
/* <![CDATA[ */
function GoogleFormTracker()
{
goog_snippet_vars = function() {
var w = window;
w.google_conversion_id = 949468534;
w.google_conversion_label = "9xLwCK7rm3IQ9vrexAM";
w.google_conversion_value = 1;
w.google_remarketing_only = false;
}
// DO NOT CHANGE THE CODE BELOW.
goog_report_conversion = function(url) {
goog_snippet_vars();
window.google_conversion_format = "3";
var opt = new Object();
opt.onload_callback = function() {
if (typeof(url) != 'undefined') {
window.location = url;
}
}
var conv_handler = window['google_trackConversion'];
if (typeof(conv_handler) == 'function') {
conv_handler(opt);
}
}
}
/* ]]> */
</script>
<script type="text/javascript"
src="//www.googleadservices.com/pagead/conversion_async.js">
</script>
GoogleFormTracker() fired on footer when site is load.
And also i verified my code on tag manager chrome addons(No error showing there).
but i don't know where to showing me how many time this function is fired ?
let me know any mistake in my code or where is showing tracking value in add word (with screenshot and step by step).
Thanks
In google add word account follow below step
Tool->Attribution
In Attribution available you conversation value.
I hope u need like above
"but i don't know where to showing me how many time this function is fired". Not entirely sure I understand, but perhaps you just need to put a console.log('marco'); inside the function and view the browser console (ctrl + shift + i) to see how many times the function is called?

Check if Javascript script exists on page

I have a bookmarklet that I've made and it loads a script from my server onto the users current page. However I have an if check in my script that if a condition is not met then no action is taken. However if the user then meets that condition then the code is run, but has caused there to be two sets of scripts inserted into their page. Can i prevent this?
<a href="javascript: (function () {
var jsCode = document.createElement('script');
jsCode.setAttribute('src', 'http://xxx.co.uk/xxx/script.js');
document.body.appendChild(jsCode);
}());">Bookmarklet</a>
You can check whether your script is loaded like this:
function isMyScriptLoaded(url) {
if (!url) url = "http://xxx.co.uk/xxx/script.js";
var scripts = document.getElementsByTagName('script');
for (var i = scripts.length; i--;) {
if (scripts[i].src == url) return true;
}
return false;
}
Alternatively, you could do something like this:
<a href="javascript:
if (!jsCode) {
var jsCode = document.createElement('script');
jsCode.setAttribute('src', 'http://xxx.co.uk/xxx/script.js');
document.body.appendChild(jsCode);
}
">Bookmarklet</a>
This "pollutes" the global namespace with the jsCode variable, but that might be a necessary evil. You could rename it to something that is unlikely to appear in the document where the bookmarklet is run.
Please note that while the javascript URI scheme is okay for bookmarklets as in this case, it's not considered to be a good practice for normal use.
Just check the selector length. Here's an example using jQuery:
if ($('script[src="http://xxx.co.uk/xxx/script.js"]').length > 0) {
//script exists
}
You can place id attributes on your script tags and use document.getElementById('your-id') to identify whether the script is on the page before adding.
if (!document.getElementById('your-id')) {
// append your script to the document here, ensure it has its id attribute set to 'your-id'
}
Solution with ES6, no jQuery:
const url = 'http://xxx.co.uk/xxx/script.js';
function scriptExists(url) {
return document.querySelectorAll(`script[src="${url}"]`).length > 0;
}
if(scriptExists(url)) {
...
}
It's not recommended to inline JS into HTML. Instead add event listeners:
function bookmark() {
if(scriptExists(url)) {
...
}
}
const button = document.querySelectorAll('a.bookmark');
button.addEventListener('click', bookmark, false);
In case working with local and live alternatively.
The exact URL may change. I think the ID method is better.
This is a combination of Two StackOverflow answers.
if (!document.getElementById('your-id')) {
addScript("your_script_src"); //adding script dynamically
addCSSFile("your_css_src"); // adding css files
}
function addScript(path) {
var head = document.getElementsByTagName("head")[0];
var s = document.createElement("script");
s.type = "text/javascript";
s.src = path;
s.id = "your-id";
head.appendChild(s);
}
function addCSSFile(path) {
var head = document.getElementsByTagName("head")[0];
var s = document.createElement("style");
s.type = "text/css";
s.src = path;
head.appendChild(s);
}
if you create a variable in the global scope (window.yourVariable) and check if that exists already then you can decide if you want to add your jsCode snippet code or run whatever you are running in script.js
if (document.getElementById('element-id')) {
// if exist must do something
}
hi, this is worked for me, please try it if you still need it

innerHTML to insert script in body (for ZeroClipboard) not working

I'm building <div> elements using AJAX, and I want to add ZeroClipboard functionality. Firebug shows the code is building correctly, and when I copy it into a raw HTML test page it works too. The builds are not happening at onload, but down the track.
The code is as follows, calling some functions that create the new elements:
dom_append_child_with_onclick ("img",export_id,"icon_active",report_heading_id, "event.cancelBubble = true;");
dom_append_child ("div",export_script_id,"",report_heading_id);
text = "<script language='JavaScript'>var clip" +rnum +"=new ZeroClipboard.Client();clip"+rnum+".setText('');clip"+rnum+".addEventListener('mouseDown',function(client){alert('firing');clip"+rnum+".setText(document.getElementById('SL40').value);});clip"+rnum+".glue('XR"+rnum+"','RH"+rnum+"');</script>";
document.getElementById(export_script_id).innerHTML=text;
My question: when you insert a script into the <body>, do you have to do something to get it to fire? The script appears not to be doing its thing, and I can't get the alert 'firing' to display.
Note: the cancelBubble is to stop the onClick function of the underlying element. It may be unnecessary if I can get the flash working.
Thanks.
You can just inject your script into the page as a DOM object, but this does not work in all browsers:
var s = document.createElement("script");
s.type = "text/javascript";
s.innerText = "var clip" +rnum +"=new ZeroClipboard.Client();clip"+rnum+".setText('');clip"+rnum+".addEventListener('mouseDown',function(client){alert('firing');clip"+rnum+".setText(document.getElementById('SL40').value);});clip"+rnum+".glue('XR"+rnum+"','RH"+rnum+"');";
document.getElementsByTagName("head")[0].appendChild(s);
Or, for better compatibility, you probably want to just declare a function which sets this up in your page, and then just call the function with the rnum as the parameter.
e.g.
function useZeroClipboard(rnum) {
window["clip" + rnum] = new ZeroClipboard.Client();
cwindow["clip" + rnum].setText('');
window["clip" + rnum].addEventListener('mouseDown', function(client){
alert('firing');
window["clip" + rnum].setText(document.getElementById('SL40').value);
});
window["clip" + rnum].glue('XR"+rnum+"','RH"+rnum+"');
}
Then you can just call that in your code:
useZeroClipboard(rnum);
Instead of writing the script block.
Here is a method that recursively replaces all scripts with executable ones:
function replaceScriptsRecurse(node) {
if ( nodeScriptIs(node) ) {
var script = document.createElement("script");
script.text = node.innerHTML;
node.parentNode.replaceChild(script, node);
}
else {
var i = 0;
var children = node.childNodes;
while ( i < children.length) {
replaceScriptsRecurse( children[i] );
i++;
}
}
return node;
}
function nodeScriptIs(node) {
return node.getAttribute && node.getAttribute("type") == "text/javascript";
}

Categories