Prevent parts of html from loading in mobile - html

I have used css and media queries till now to prevent images from loading. Now i have to requirement to prevent parts of html, scripts from loading in mobile browsers.
Here is how i used to prevent images from loading
#media (min-width:601px) {
.image {
background-image: url(http://www.example.com/wp-content/uploads/2013/05/img.jpg);
width:700px;
height:350px;
}
}
Any suggestions for HTML and JavaScript ?

You just can prevent HTML parsing in browser by CDATA or HTML comments. But you must change your server side/template generated code to prevent loading any HTML code.
Also you can't prevent loading script from script tag src attribute. You can use window.matchMedia and lazy-load/async for loading script:
if (window.matchMedia('min-width:601px')) {
(function (callback) {
var script = document.createElement('script');
script.src ='url';
script.onload = callback;
document.documentElement.firstChild.append(script);
})(callback/*if needed*/)
}
Or using requirejs:
if (window.matchMedia('min-width:601px')) {
var someModule = require('moduleName_or_path');
}
Also you can use enquirejs.

Take a look at this:
http://css-tricks.com/snippets/css/media-queries-for-standard-devices/
If you want to use javascript of jQuery:
What is the best way to detect a mobile device in jQuery?
Of course add a display: none on the element you want to hide after detecting if on mobile device.

Here's some JavaScript code that you can run to include desktop-only JS and remove unwanted HTML elements from mobile browsers.
if (window.innerWidth > 601) {
//Run JS code that is to be loaded only on desktop browsers
console.log("This will run only in desktop browsers");
}
if (window.innerWidth < 601) {
//Remove HTML elements not to be shown in mobile devices
document.getElementById("extra-info").remove();
}

Related

Is there a way so that I can make reCaptcha responsive to div

Is there a way so that I can make it fit inside and responsive too?
** UPDATE IN QUESTION ** : I Can't change recaptcha code because my backend validates the recaptcha
Please let me know If I can make changes in side that element,Thanks
Google reCaptcha is generated as an iframe so it has its complete own set of CSS/else libraries and that makes it very hard ~ impossible to edit it because of the Same-domain policy.
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
You can set the data-size attribute to compact that could help
<div class="g-recaptcha" data-sitekey="your_site_key" data-size="compact"></div>
https://developers.google.com/recaptcha/docs/display
Since you can't modify the HTML source, you can use jQuery to add the data-size attribute to the g-recaptcha div. Make sure you load jQuery somewhere using the CDN too. Inspect the page with DevTools, find the div, then target its class or ID using JS and use .attr() to add the attribute to it.
$('.g-recapatcha').attr('data-size','compact');
You can adjust the width of iframe in your CSS even if you can't change the code in HTML.
#media only screen and (max-width:480px){
iframe{
position: relative;
width:70%;
left: -69px;
}
}
You should listen avia and use data-size attribute: compact or normal,
I have for my web, DOMContentLoaded on top, which check if screen is smaller as px,
then setAttributeinto div. Check out:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
if (window.innerWidth < 476) {
document.getElementById("recaptcha-div").setAttribute('data-size','compact');
}else{
document.getElementById("recaptcha-div").setAttribute('data-size','normal');
};
});
</script>
<div id="recaptcha-div" class="g-recaptcha" data-theme="dark" data-sitekey="xxxx"></div>

Styling dynamically generated HTML [duplicate]

How can I control the background image and colour of a body element within an iframe? Note, the embedded body element has a class, and the iframe is of a page that is part of my site.
The reason I need this is that my site has a black background assigned to the body, and then a white background assigned to divs that contain text. A WYSIWYG editor uses an iframe to embed content when editing, but it doesn't include the div, so the text is very hard to read.
The body of the iframe when in the editor has a class that isn't used anywhere else, so I'm assuming this was put there so problems like this could be solved. However, when I apply styles to class.body they don't override the styles applied to body. The weird thing is that the styles do appear in Firebug, so I've no idea what's going on!
Thanks
UPDATE - I've tried #mikeq's solution of adding a style to the class that is the body's class. This doesn't work when added to the main page's stylesheet, but it does work when added with Firebug. I'm assuming this is because Firebug is applied to all elements on the page whereas the CSS is not applied within iframes. Does this mean that adding the css after window load with JavaScript would work?
The below only works if the iframe content is from the same parent domain.
The following code works for me. Tested on Chrome and IE8. The inner iframe references a page that is on the same domain as the parent page.
In this particular case, I am hiding an element with a specific class in the inner iframe.
Basically, you just append a style element to the head section of the document loaded in a frame:
frame.addEventListener("load", ev => {
const new_style_element = document.createElement("style");
new_style_element.textContent = ".my-class { display: none; }"
ev.target.contentDocument.head.appendChild(new_style_element);
});
You can also instead of style use a link element, for referencing a stylesheet resource.
An iframe is a 'hole' in your page that displays another web page inside of it. The contents of the iframe is not in any shape or form part of your parent page.
As others have stated, your options are:
give the file that is being loaded in the iframe the necessary CSS
if the file in the iframe is from the same domain as your parent, then you can access the DOM of the document in the iframe from the parent.
You cannot change the style of a page displayed in an iframe unless you have direct access and therefore ownership of the source html and/or css files.
This is to stop XSS (Cross Site Scripting)
This code uses vanilla JavaScript. It creates a new <style> element. It sets the text content of that element to be a string containing the new CSS. And it appends that element directly to the iframe document's head.
Keep in mind, however, that accessing elements of a document loaded from another origin is not permitted (for security reasons) -- contentDocument of the iframe element will evaluate to null when attempted from the browsing context of the page embedding the frame.
var iframe = document.getElementById('the-iframe');
var style = document.createElement('style');
style.textContent =
'body {' +
' background-color: some-color;' +
' background-image: some-image;' +
'}'
;
iframe.contentDocument.head.appendChild(style);
Override another domain iframe CSS
By using part of SimpleSam5's answer, I achieved this with a few of Tawk's chat iframes (their customization interface is fine but I needed further customizations).
In this particular iframe that shows up on mobile devices, I needed to hide the default icon and place one of my background images. I did the following:
Tawk_API.onLoad = function() {
// without a specific API, you may try a similar load function
// perhaps with a setTimeout to ensure the iframe's content is fully loaded
$('#mtawkchat-minified-iframe-element').
contents().find("head").append(
$("<style type='text/css'>"+
"#tawkchat-status-text-container {"+
"background: url(https://example.net/img/my_mobile_bg.png) no-repeat center center blue;"+
"background-size: 100%;"+
"} "+
"#tawkchat-status-icon {display:none} </style>")
);
};
I do not own any Tawk's domain and this worked for me, thus you may do this even if it's not from the same parent domain (despite Jeremy Becker's comment on Sam's answer).
An iframe has another scope, so you can't access it to style or to change its content with javascript.
It's basically "another page".
The only thing you can do is to edit its own CSS, because with your global CSS you can't do anything.
This should work with cross domain if you're the owner of the both
The trick here is to assign a global css variable to your body, to listen message with the new color, and then to change the global css variable once receive a message.
I'm using angular, but it should work with pure javascript
My use case was to show to the user what he how the color change would impact his website in the iframe before saving it
Domain A
#ViewChildren('iframeContainer') iframeContainer: QueryList<ElementRef>
sendDataToIframe(
data = {
type: 'colorChange',
colors: {primary: '#000', secondary: '#fff'},
},
): void {
if (this.targetUrl)
this.iframeContainer.first.nativeElement.contentWindow.postMessage(data) // You may use document.getElementById('iframeContainer') instead
}
Domain B
acceptedEditOrigins = [
'https://my.origine.ccom', // Be sur to have a correct origin, to avoid xss injecto: https://en.wikipedia.org/wiki/Cross-site_scripting
]
constructor() {
// Listen to message
window.addEventListener('message', (event) => this.receiveMessage(event), false)
}
receiveMessage(event: MessageEvent) {
if (this.acceptedEditOrigins.includes(event.origin))
switch (event.data.type) {
case 'colorChange': {
this.setWebsiteConfigColor(event.data.colors)
}
}
}
setWebsiteConfigColor(colors: WebsiteConfigColors) {
if (colors) {
const root = document.documentElement
for (const [key, value] of Object.entries(colors)) {
root.style.setProperty(`--${key}`, value) // --primary: #000, --secondary: #fff
}
}
}
body {
background-color: var(--primary);
}
If you have control of the page hosting the iframe and the page of the iframe, you can pass a query parameter to the iframe...
Here's an example to add a class to the iframe based on whether or not the hosting site is mobile...
Adding iFrame:
var isMobile=$("mobile").length; //detect if page is mobile
var iFrameUrl ="https://myiframesite/?isMobile=" + isMobile;
$(body).append("<div id='wrapper'><iframe src=''></iframe></div>");
$("#wrapper iframe").attr("src", iFrameUrl );
Inside iFrame:
//add mobile class if needed
var url = new URL(window.location.href);
var isMobile = url.searchParams.get("isMobile");
if(isMobile == "1") {
$("body").addClass("mobile");
}
For juste one iframe, you can do something like this:
document.querySelector('iframe').contentDocument.body.style.backgroundColor = '#1e1e2d';
In case you have multiple iframe you're dealing with:
document.querySelectorAll('iframe').forEach((iframe) => {
iframe.contentDocument.body.style.backgroundColor = '#1e1e2d';
});
Perhaps it's changed now, but I have used a separate stylesheet with this element:
.feedEkList iframe
{
max-width: 435px!important;
width: 435px!important;
height: 320px!important;
}
to successfully style embedded youtube iframes...see the blog posts on this page.
give the body of your iframe page an ID (or class if you wish)
<html>
<head></head>
<body id="myId">
</body>
</html>
then, also within the iframe's page, assign a background to that in CSS
#myId {
background-color: white;
}

Overwrite css of an external widget [duplicate]

How can I control the background image and colour of a body element within an iframe? Note, the embedded body element has a class, and the iframe is of a page that is part of my site.
The reason I need this is that my site has a black background assigned to the body, and then a white background assigned to divs that contain text. A WYSIWYG editor uses an iframe to embed content when editing, but it doesn't include the div, so the text is very hard to read.
The body of the iframe when in the editor has a class that isn't used anywhere else, so I'm assuming this was put there so problems like this could be solved. However, when I apply styles to class.body they don't override the styles applied to body. The weird thing is that the styles do appear in Firebug, so I've no idea what's going on!
Thanks
UPDATE - I've tried #mikeq's solution of adding a style to the class that is the body's class. This doesn't work when added to the main page's stylesheet, but it does work when added with Firebug. I'm assuming this is because Firebug is applied to all elements on the page whereas the CSS is not applied within iframes. Does this mean that adding the css after window load with JavaScript would work?
The below only works if the iframe content is from the same parent domain.
The following code works for me. Tested on Chrome and IE8. The inner iframe references a page that is on the same domain as the parent page.
In this particular case, I am hiding an element with a specific class in the inner iframe.
Basically, you just append a style element to the head section of the document loaded in a frame:
frame.addEventListener("load", ev => {
const new_style_element = document.createElement("style");
new_style_element.textContent = ".my-class { display: none; }"
ev.target.contentDocument.head.appendChild(new_style_element);
});
You can also instead of style use a link element, for referencing a stylesheet resource.
An iframe is a 'hole' in your page that displays another web page inside of it. The contents of the iframe is not in any shape or form part of your parent page.
As others have stated, your options are:
give the file that is being loaded in the iframe the necessary CSS
if the file in the iframe is from the same domain as your parent, then you can access the DOM of the document in the iframe from the parent.
You cannot change the style of a page displayed in an iframe unless you have direct access and therefore ownership of the source html and/or css files.
This is to stop XSS (Cross Site Scripting)
This code uses vanilla JavaScript. It creates a new <style> element. It sets the text content of that element to be a string containing the new CSS. And it appends that element directly to the iframe document's head.
Keep in mind, however, that accessing elements of a document loaded from another origin is not permitted (for security reasons) -- contentDocument of the iframe element will evaluate to null when attempted from the browsing context of the page embedding the frame.
var iframe = document.getElementById('the-iframe');
var style = document.createElement('style');
style.textContent =
'body {' +
' background-color: some-color;' +
' background-image: some-image;' +
'}'
;
iframe.contentDocument.head.appendChild(style);
Override another domain iframe CSS
By using part of SimpleSam5's answer, I achieved this with a few of Tawk's chat iframes (their customization interface is fine but I needed further customizations).
In this particular iframe that shows up on mobile devices, I needed to hide the default icon and place one of my background images. I did the following:
Tawk_API.onLoad = function() {
// without a specific API, you may try a similar load function
// perhaps with a setTimeout to ensure the iframe's content is fully loaded
$('#mtawkchat-minified-iframe-element').
contents().find("head").append(
$("<style type='text/css'>"+
"#tawkchat-status-text-container {"+
"background: url(https://example.net/img/my_mobile_bg.png) no-repeat center center blue;"+
"background-size: 100%;"+
"} "+
"#tawkchat-status-icon {display:none} </style>")
);
};
I do not own any Tawk's domain and this worked for me, thus you may do this even if it's not from the same parent domain (despite Jeremy Becker's comment on Sam's answer).
An iframe has another scope, so you can't access it to style or to change its content with javascript.
It's basically "another page".
The only thing you can do is to edit its own CSS, because with your global CSS you can't do anything.
This should work with cross domain if you're the owner of the both
The trick here is to assign a global css variable to your body, to listen message with the new color, and then to change the global css variable once receive a message.
I'm using angular, but it should work with pure javascript
My use case was to show to the user what he how the color change would impact his website in the iframe before saving it
Domain A
#ViewChildren('iframeContainer') iframeContainer: QueryList<ElementRef>
sendDataToIframe(
data = {
type: 'colorChange',
colors: {primary: '#000', secondary: '#fff'},
},
): void {
if (this.targetUrl)
this.iframeContainer.first.nativeElement.contentWindow.postMessage(data) // You may use document.getElementById('iframeContainer') instead
}
Domain B
acceptedEditOrigins = [
'https://my.origine.ccom', // Be sur to have a correct origin, to avoid xss injecto: https://en.wikipedia.org/wiki/Cross-site_scripting
]
constructor() {
// Listen to message
window.addEventListener('message', (event) => this.receiveMessage(event), false)
}
receiveMessage(event: MessageEvent) {
if (this.acceptedEditOrigins.includes(event.origin))
switch (event.data.type) {
case 'colorChange': {
this.setWebsiteConfigColor(event.data.colors)
}
}
}
setWebsiteConfigColor(colors: WebsiteConfigColors) {
if (colors) {
const root = document.documentElement
for (const [key, value] of Object.entries(colors)) {
root.style.setProperty(`--${key}`, value) // --primary: #000, --secondary: #fff
}
}
}
body {
background-color: var(--primary);
}
If you have control of the page hosting the iframe and the page of the iframe, you can pass a query parameter to the iframe...
Here's an example to add a class to the iframe based on whether or not the hosting site is mobile...
Adding iFrame:
var isMobile=$("mobile").length; //detect if page is mobile
var iFrameUrl ="https://myiframesite/?isMobile=" + isMobile;
$(body).append("<div id='wrapper'><iframe src=''></iframe></div>");
$("#wrapper iframe").attr("src", iFrameUrl );
Inside iFrame:
//add mobile class if needed
var url = new URL(window.location.href);
var isMobile = url.searchParams.get("isMobile");
if(isMobile == "1") {
$("body").addClass("mobile");
}
For juste one iframe, you can do something like this:
document.querySelector('iframe').contentDocument.body.style.backgroundColor = '#1e1e2d';
In case you have multiple iframe you're dealing with:
document.querySelectorAll('iframe').forEach((iframe) => {
iframe.contentDocument.body.style.backgroundColor = '#1e1e2d';
});
Perhaps it's changed now, but I have used a separate stylesheet with this element:
.feedEkList iframe
{
max-width: 435px!important;
width: 435px!important;
height: 320px!important;
}
to successfully style embedded youtube iframes...see the blog posts on this page.
give the body of your iframe page an ID (or class if you wish)
<html>
<head></head>
<body id="myId">
</body>
</html>
then, also within the iframe's page, assign a background to that in CSS
#myId {
background-color: white;
}

How to browse between pages without screen flickering?

I have two classic HTML pages (just HTML and CSS) and links between them.
When I click on these links, the screen flickers (it quickly goes white between transitions).
I tried to place this in the head - without result:
<meta http-equiv="Page-Enter" content="blendTrans(Duration=0.0)" />
<meta http-equiv="Page-Exit" content="blendTrans(Duration=0.0)" />
I can usually open other sites without the flickering.
Browser is Firefox 16.0.1.
Just change your body background to:
body {
background: url("Images/sky01.jpg") repeat scroll 0 0 #121210;
font-family: Verdana,Geneva,sans-serif;
font-size: 12px;
margin: 0;
padding: 0;
}
background color will prevent white flickering while loading the background image.
That meta are for IE only, they don't work in FF.
You can't rely prevent flickering in plain HTML. The best solution I found is to replace every link with a JavaScript call where you download the page with AJAX and then you replace the document itself with the new content. Page refresh will be really fast and you won't see any blank screen while downloading.
Basic function may be something like this:
function followLink(pageUrl)
{
jQuery.ajax({
url: pageUrl,
type: "GET",
dataType: 'html',
success: function(response){
document.getElementsByTagName('html')[0].innerHTML = response
}
});
}
Then you have to replace you links from:
Link
With:
Link
More details about this: replace entire HTML document]1: how to replace the content of an HTML document using jQuery and its implications (not always so obvious).
Improvements
With this solution you force your users to use JavaScript, in case it's not enable they won't be able to click links. For this reason I would provide a fallback. First do not change <a> but decorate them with (for example) a CSS class like async-load. Now on the onload of the page replace all hrefs with their javascript: counterpart, something like this:
jQuery().ready(function() {
jQuery("a.asynch-load").each(function() {
this.href = "javascript:followLink(\"" + this.href + "\")";
});
});
With this you can handle a loading animation too (how it's implemented depends on what yuo're using and your layout). Moreover in the same place you can provide fade in/out animations.
Finally do not forget that this technique can be used for fragments too (for example if you provide a shared navigation bar and a content sections replaced when user click on a link the the navigation bar (so you won't need to load everything again).
Try to embed pictures as it delays final page loading and therefore white transition time
echo '<img src="data:image/png;base64,';
echo base64_encode(file_get_contents($file));
echo '"/>';

Load HTML frames in a specific order without back button problems?

I have a web page that uses a frameset.
Due to scripting and object dependencies, I need to load the frames in a specific order.
I have used this example as a template:
The JavaScript Source: Navigation: Frames Load Order
This loads an empty page in place of the page I need to load last, then replaces it with the correct page after the first page has loaded.
However: I also need to use the browser Back button. If you run the sample at the above link, let both frames load, then click the Back button, the top frame reverts to the temporary blank page. It is then necessary to click the Back button again to navigate to the page before the frameset.
Is there a way to force frames to load in a specific order without this Back button behavior - or a way to force the Back button to skip the empty page?
This needs to work with Internet Explorer 6 and 7 and preferably with Firefox 3 as well.
You mention this quite a lot in this post...
This is a legacy system. The frameset is required.
If you are working on a legacy system, then I think it is time you accepted how framesets behave in terms of the browser's back button. If it is truly a legacy system, you don't need to fix this behaviour. If it is actually NOT a legacy system and you need to fix this problem, you need to get away from using a frameset. Framesets were deprecated from the HTML standards and shouldn't be used.
Why not use three iframes in the desired order, then resize/move them to the appropriate places?
<iframe id="a1" src="page-to-load-first.htm"></iframe>
<iframe id="a2" src="page-to-load-second.htm"></iframe>
<iframe id="a3" src="page-to-load-third.htm"></iframe>
<script>
function pos(elem,x,y,w,h) {
if (!elem.style) elem=document.getElementById(elem);
elem.style.position='absolute';
elem.style.top = y+'px';
elem.style.left= x+'px';
elem.style.width=w+'px';
elem.style.height=h+'px';
}
window.onload = function() {
window.onresize=function() {
var w = window.innerWidth || document.documentElement.clientWidth;
var h = window.innerHeight || document.documentElement.clientHeight;
var w3 = w/3;
var h2 = h/2;
pos('a1',0,0,w3,h); /* left 1/3rd */
pos('a2',w3,0,w3+w3,h2);
pos('a3',w3,h2,w3+w3,h2);
};
window.onresize();
};
</script>
Build the frames themselves using JavaScript:
<html>
<head>
<script>
function makeFrame(frameName) {
var newFrame = document.createElement('frame');
newFrame.id=frameName;
if(frameName=="B") {
newFrame.onload=function() {makeFrame("C")};
newFrame.src = 'http://www.google.com';
}
else {
newFrame.src = 'http://www.yahoo.com';
}
document.getElementById('A').appendChild(newFrame);
}
</script>
</head>
<frameset name='A' id='A' rows="80, *" onload="makeFrame('B')"></frameset>
</html>