Is there anyway of disabling loading external content inside of an iFrame?
Imagine there is a an iframe defined like:
<iframe srcdoc="
<html>
<head>
<title>Example Page!</title>
<link rel='stylesheet' type='text/css' href='http://example.com/mystyle.css'>
</head>
<body>
<p class='main'>Here goes the text.
</p>
<script src='http://example.com/js/superscript.js'>
</body>
</html>">
</iframe>
The loading of JS can be disabled with the allow-scripts inside of the sanbox attribute, but is there any way of disabling the load of the external css (and other external content)?
If not, is there any replacement for "rendering" html code (for example by JS), which would enable this?
I've made the following function to remove loading some assets from emails displayed in an iframe:
const replaced = []
const h = html
.replace(/url\s*\(([\s\S]+?)\)/g, (m,url) => {
url = url.trim()
try {
url = decodeURIComponent(url)
} catch (err) {/**/}
replaced.push(url)
return 'url()'
})
.replace(/[\s'"](?:src|srcset|background)?\s*=\s*(['"])([^\1]*?)\1/g, (m,q,src) => {
if (!src) return m // empty
replaced.push(src)
return ''
})
.replace(/<\s*link[^>]*?([\s'"]href\s*=\s*(['"])([^\2]*?)\2)/g, (m,attr,q,src) => {
if (!src) return // empty
replaced.push(src)
return m.replace(attr, '')
})
interestingly, <img alt="test"src="http://src.com/img.jpg"> is valid and will be displayed by chrome so whitespace before an attribute is actually not required, so I edited this answer to account for that...
It's probably not perfect, but you can tweak it as you see more cases by adding attributes...
Yes you can achieve it by using src not srcdoc and prefixing with data:text/html;charset=UTF-8,.
In your example:
<iframe src="data:text/html;charset=UTF-8,<html> <head> <title>Example Page!</title> <link rel='stylesheet' type='text/css' href='http://example.com/mystyle.css'> </head> <body> <p class='main'>Here goes the text. </p><script src='http://example.com/js/superscript.js'> </body> </html>">
</iframe>
Related
I have a simple text file in the same directory as HTML file , I used the fetch command in javascript to display the text file content in the page div section when the loading of the page finish
however, my code doesn't work and nothing has been displayed, my question is does the fetch command suitable for such a task or should I use filereader ?
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Untitled Page</title>
<meta name="generator" >
<style type="text/css">
</style>
<script type="text/javascript" defer>
const myfile=location.href.slice(0,location.href.lastIndexOf("/"))+"/a.txt"
console.log(myfile);
async function getTextFile1() {
try {
const response = await fetch(myfile, { mode: 'no-cors' });
const fileText = await response.text();
//console.log(window.location);
//console.log(window.location.href);
const tagElement = document.getElementById("about_layer");
tagElement.innerText = fileText;
} catch (error) {
console.log(error);
}
}
window.onload = getTextFile1;
</script>
</head>
<body>
<div >should be placed here </div>
<div id="about_layer">
</div>
</body>
</html>
There is nothing wrong with your code , just try running your html file using development server .
You can use Live Server visual studio code extension for that.
Im using botman.io package for chatboot widget.
Everything works perfectly but problem is that i can't change default background color of chat widget. On inspect console it shown that boman widget calls ( https://cdn.jsdelivr.net/npm/botman-web-widget#0.0.20/build/assets/css/chat.css ) link, but i cant find that call on my localhost project. If anyone know solution i would appreciate.
<script src="{{ asset('/js/webflow.js') }}"></script>
<script>
var botmanWidget = {
title:'Scarletbot',
introMessage: 'Hello, I am a Scarlet! I am here to assist you and answer all your questions about our products and services!',
mainColor:'#c02026',
aboutText:'',
bubbleBackground:'#c02026',
headerTextColor: '#fff',
};
</script>
<script id="botmanWidget" src="{{ asset('/js/widget.js') }}"></script>
You may add frameEndpoint in
var botmanWidget = {
frameEndpoint: '<?php echo base_url('botdemo/chatserver1');?>',
title:'Scarletbot',
introMessage: 'Hello, I am a Scarlet! I am here to assist you and answer all your questions about our products and services!',
mainColor:'#c02026',
aboutText:'',
bubbleBackground:'#c02026',
headerTextColor: '#fff',
};
frameEndpoint is nothing but source of iframe loaded by botman-widget
frameEndpoint source is like :
<!doctype html>
<html>
<head>
<title>BotMan Widget</title>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/botman-web-widget#0/build/assets/css/chat.min.css">
</head>
<body>
<script id="botmanWidget" src='https://cdn.jsdelivr.net/npm/botman-web-widget#0/build/js/chat.js'></script>
</body>
</html>
Here you may use own css as well.
I quickly checked out the web widget on the botman github.
There is a simple link to the chat.css in the head of chat.html located in the src folder.
This points to assets/css/chat.css, which you can edit freely and add a background-color to.
I use brute force in the iframe to change background with jquery
$(document).on('click', '.desktop-closed-message-avatar img', function() {
var iframe = document.getElementById("chatBotManFrame");
iframe.addEventListener('load', function () {
var htmlFrame = this.contentWindow.document.getElementsByTagName("html")[0];
var bodyFrame = this.contentWindow.document.getElementsByTagName("body")[0];
var headFrame = this.contentWindow.document.getElementsByTagName("head")[0];
var image = "https://images.unsplash.com/photo-1501597301489-8b75b675ba0a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1349&q=80"
htmlFrame.style.backgroundImage = "url("+image+")";
bodyFrame.style.backgroundImage = "url("+image+")";
});
});
Well, i am new to Ajax and JQuery, I struggled to compile this. I'm trying to load URL with ajax navigation and with popstate retrieving back and front navigations. The below code works well but my problem is integrating the Progress Indicator of the page i'm trying to load when the link is clicked using Pace Page Progress Bar Plugin.
<html>
<head>
<meta charset="utf-8" />
<div id="render-me">
<title>jQuery Ajax Test</title>
<script type="text/javascript" src=" https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://www.gossipper.com/content/css/inspired-mob/styles/pace-theme-center-atom.css" />
<script>
paceOptions = {
ajax: true, // disabled
document: true, // disabled
eventLag: true, // disabled
elements: {
selectors: ['#render-me']
}
};
</script>
<script src="https://www.gossipper.com/content/css/inspired-mob/js/pace.js"></script>
<script type="text/javascript"><!--
$(document).ready(function(e){
$.ajaxSetup ({
cache: false
});
var page;
$('a.lnk').click(function(){
page = $(this).attr('href');
$('#render-me').load(page + ' #render-me');
if(page != location.href){
window.history.pushState({path:page},'',page);
$(window).bind("popstate", function() {
link = location.pathname.replace(/^.*[\\/]/, ""); // get filename only
$('#render-me').load(link + ' #render-me');
});
}
return false;
});
document.addEventListener('gg', function(){
document.querySelector('.pace').classList.remove('pace-inactive');
document.querySelector('.pace').classList.add('pace-active');
document.querySelector('.pace-progress').setAttribute('data-progress-text', percentComplete.value + '%');
document.querySelector('.pace-progress').setAttribute('style', '-webkit-transform: translate3d(' + percentComplete.value + '%, 0px, 0px)');
});
$(window).on({
popstate:function(e){
page = location.href;
$('#render-me').load(page + ' #render-me');
}
});
});
</script>
</head>
<body>
<h1>Web page test.html</h1>
Get extern
<div id="content">Initial content in test.html</div>
</body>
</div>
</html>
As i stated above, am a newbie to Ajax, JQuery and Javascript. I struggled to compile this, i need help getting this to work.
The problem in your code is your script source for pace, css source for pace and the proper placing of html elements.
I tried to go in the sources of your script and css for pace but it is not found.
You don't need to encapsulate all of your element in the <div id="render-me">.
Based from https://www.w3schools.com/html/html_head.asp
The <head> element is a container for metadata (data about data) and is placed between the <html> tag and the <body> tag.
HTML metadata is data about the HTML document. Metadata is not displayed.
Metadata typically define the document title, character set, styles, links, scripts, and other meta information.
The following tags describe metadata: <title>, <style>, <meta>, <link>, <script>, and <base>
So you must remove the div in the head, fix the sources and put the <div id="render-me"> inside body.
Here is your code that I fixed: https://jsfiddle.net/uqbysq1a/1/
Here is the example I prepared to tell about the problem easier.
http://codepen.io/anon/pen/EVpYXm
As you can see the initial <html> is set to display a text:
"This is the old html!"
It sets the whole content to the data in the variable myHtml. however here is what I notice:
the style is not carried from the <body> element. Moreover, the <body> element is somehow not created at all!
Here is the sring myHtml, tidied up to display as an html:
<html>
<head>
<title>Title Here</title>
<link href='style.css' rel='stylesheet' type='text/css'/>
</head>
<body style='background-color: red'>
<div>Div!</div>
</body>
</html>
I've realized that when link element is removed, everything works fine. Try it, see it yourself.
Stuck with this issue for the last few hours. Looking for a result.
Here is the full code:
page html:
<html>
This is the old html!
</html>
javascript:
$(function(){
var myHtml = "<html><head><title>Title Here</title><link href='style.css' rel='stylesheet' type='text/css'/></head><body style='background-color: red'><div>Div!</div></body></html>"
$("html").html(myHtml);
})
The main purpose of this question is to understand the reason of this behavior as well as finding the best solution.
The issue is that, when you use jQuery's html(val), it does something like this:
html: function(value) {
/* ... */
// See if we can take a shortcut and just use innerHTML
if ( typeof value === "string" && !rnoInnerhtml.test( value ) && /* ... */) {
/* ... */ elem.innerHTML = value; /* ... */
}
/* ... */
}
That is, it checks the string with the regex rnoInnerhtml, which is
rnoInnerhtml = /<(?:script|style|link)/i
Therefore, presumably to avoid inserting stylesheets, jQuery avoids innerHTML and does complicated things with domManip.
I recommend using native innerHTML:
$("html").prop('innerHTML', myHtml);
var myHtml = "<head><title>Title Here</title><link href='style.css' rel='stylesheet' type='text/css'/></head><body style='background-color: red'><div>Div!</div></body>"
$("html").prop('innerHTML', myHtml);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
This is the old html!
Or with vanilla-js:
document.documentElement.innerHTML = myHtml;
var myHtml = "<head><title>Title Here</title><link href='style.css' rel='stylesheet' type='text/css'/></head><body style='background-color: red'><div>Div!</div></body>"
document.documentElement.innerHTML = myHtml;
This is the old html!
The problem is that you're appending an html element inside the root html element, which is undefined behavior and cannot be rendered reliably by the browser. Strip the opening and closing <html> and </html> tags from your myHtml string and it works!
Working demo
$(function() {
var myHtml = "<head><title>Title Here</title></head><body style='background-color: red; '><div>Div!</div></body>"
$('html').html(myHtml);
})
Alternatively, you could keep the tags and write directly to the document object instead, which opens a new stream and overwrites the previous document.
// ...
document.write(myHtml);
I'm building a small application in Play and have an 'outer' template which holds all my CSS and JS imports (jQuery and my main.js file). CSS at the top, JS at the bottom with a body tag in between... pretty basic stuff:
<html>
<head>
<title>test</title>
<link rel="stylesheet" href="#routes.Assets.at("stylesheets/foundation.css")">
<link rel="stylesheet" href="#routes.Assets.at("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="#routes.Assets.at("images/favicon.png")">
</head>
<body>
#content
</body>
<script src='#routes.Assets.at("javascripts/jquery-1.9.0.min.js")' type="text/javascript"></script>
<script src='#routes.Assets.at("javascripts/index.js")' type="text/javascript"> </script>
</html>
Which is fine.
However, I have page specific javascript functions that should run based on what the page is. So if I go to localhost:9000/test, I want a particular set of functions to run.
If I go to localhost:9000/chips, I want another set of functions to run.
I can't see a neat way of doing this, really, except checking the current page url in the script and executing functions based on that... but the routes file is already doing stuff based on the current page url - seems strange to have to do something so similar twice.
One solution is to put all my scripts at the top and then execute inline scripts in the HTML... but I hate doing things like that.
You have very nice and clear sample available in the... documentation.
Scroll to the bottom and check section: moreScripts and moreStyles equivalents, you have there ready to use samples.
I use a ViewModel approach to solve this issue.
The default ViewModel:
class DefaultPage(
implicit val request: RequestHeader,
implicit val lang: Lang) {
var title: String = null
val styles = mutable.LinkedHashMap.empty[String, Int]
val scripts = mutable.LinkedHashMap.empty[String, Int]
def title(title: String) {
this.title = title
}
def style(style: String)(implicit priority: Int = 500) {
styles.put(style, priority)
}
def script(script: String)(implicit priority: Int = 500) {
scripts.put(script.toString, priority)
}
def translate(message: String, objects: Any*) = Messages(message, objects: _*)
}
Then I have two template tags:
styles.scala.html
#(styles: scala.collection.mutable.Map[String, Int])
#for(style <- styles.toList.sortBy(_._2)) {
<link rel="stylesheet" href="#routes.Assets.at(style._1)" />
}
scripts.scala.html
#(scripts: scala.collection.mutable.Map[String, Int])
#for(script <- scripts.toList.sortBy(_._2)) {
<script async="true" src="#routes.Assets.at(script._1)"></script>
}
My main template:
main.scala.html
#(page: util.view.models.DefaultPage)(content: Html)
#import tags.scripts
#import tags.styles
#page.style("css/vendor/normalize.min.css")(1)
#page.style("css/vendor/formalize.min.css")(1)
#page.style("css/sprites.min.css")(1)
#page.style("css/main.min.css")(1)
#page.style("css/quirks.min.css")(1000)
#page.script("js/vendor/jquery-1.9.1.min.js")(1)
#page.script("js/vendor/jquery.formalize.min.js")(1)
#page.script("js/plugins.min.js")(1)
#page.script("js/main.min.js")(1)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>#page.title</title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width" />
#styles(page.styles)
<script src="#routes.Assets.at("js/vendor/modernizr-2.6.2.min.js")"></script>
</head>
<body class="#page.lang.code #page.lang.language #page.lang.country">
#content
#scripts(page.scripts)
</body>
And a sub template:
#(page: util.view.models.ContactUsPage)
#page.title(page.translate("contact.us.title"))
#page.style("css/contact-us.min.css")
#page.script("js/vendor/jquery.expandable-1.1.4.js")
#page.script("js/contact-us.min.js")
#main(page) {
}
You can pass your javascript which is specific to a page as template parameter link