Unable to target embedded Flickr video iframe with jQuery - javascript

I'm trying to make an embedding Flickr video be fluid on a responsive theme I'm working on for Tumblr. I'm doing well with any other embedded video or audio players (Youtube, Vimeo, Soundcloud, Spotify, etc), but Flickr videos are overlaping, being unable to contain them on their parent container.
Flickr video iframe and some of its children elements has inline css declarations which are causing the content overflows.
Here's a screenshot with the iframe structure
First I've tried to simply overwrite those styles with CSS but have no effect.
Then I tried with jQuery, but can't target the iframe.
<iframe frameborder="0" allowfullscreen="" class="flickr-embed-frame" webkitallowfullscreen="" mozallowfullscreen="" oallowfullscreen="" msallowfullscreen="" width="700" height="393" data-natural-width="1024" data-natural-height="576" style="overflow: hidden; padding: 0px; margin: 0px; width: 700px; height: 393px; max-width: none;" data-loaded="true"></iframe>
Despite the iframe has a css class .flickr-embed-frame I can't neither target it, nor its child elements. I've tried with my function inside $(document).ready() and $(window).load() with any result.
Selectors like $('.flickr-embed-frame').contents().find('.child-class'); haven't worked neither.
Inside the iframe there's a video element:
<video src="https://www.flickr.com/photos/138041208#N02/27214754585/play/hd/9ecf29781c/" width="699" height="393" poster="https://farm8.staticflickr.com/7776/27214754585_9ecf29781c_c.jpg" controls=""></video>
Also tried to target it with selectors like $('video[src^="https://www.flickr.com"]') with no result.
Couldn't find any question related, so hope someone will have a solution. Thanks.
EDIT =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Ok, I tried to manually embed a Flickr Video on a JSFiddle instead of Tumblr (where you just have to paste an URL link to the video). This is the code Flickr asks you to add on your code in order to display the video:
<a data-flickr-embed="true" href="https://www.flickr.com/photos/138041208#N02/27214754585/in/dateposted-public/" title="Test video"><img src="https://c2.staticflickr.com/8/7776/27214754585_9ecf29781c_b.jpg" width="1024" height="576" alt="Test video"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script>
Seems to be that iframe is added later, injected into the DOM via javascript. This must be the reason why I can't target the iframe, neither via CSS nor jQuery, since initially it doesn't exist.
Now my question is: How can I check when this iframe is injected to the DOM? This way I could target it and make the changes I need via jQuery.
SOLVED =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
I've finally found a solution for this problem, check my comment bellow.

Thanks to a pretty neat trick exposed by David Walsh (davidwalsh.name/detect-node-insertion) I've managed to solve this.
First we add an animation that will start when the iframe is inserted:
/* set up the keyframes; remember to create prefixed keyframes too! */
#keyframes nodeInserted {
from { opacity: 0.99; }
to { opacity: 1; }
}
The animation needs to be applied on the elements you'd like to listen for (in this case, the iframe).
.parent-container iframe {
animation-duration: 0.001s;
animation-name: nodeInserted;
}
When the animation ends, the insertion event will fire.
First, you have to create a function which acts as the event listener callback:
var insertListener = function(event){
if (event.animationName == "nodeInserted") {
// This is the debug for knowing our listener worked!
// event.target is the new node!
console.warn("Another node has been inserted! ", event, event.target);
}
}
If the animation name matches the desired animation, we know a DOM node has been injected. Now we add the event listener to the parent:
document.addEventListener("animationstart", insertListener, false); // standard + firefox
document.addEventListener("MSAnimationStart", insertListener, false); // IE
document.addEventListener("webkitAnimationStart", insertListener, false); // Chrome + Safari
Here's a demo I made with the Flickr video embedded, working fine:

Check out this previous post on SO: How to access the content of an iframe with jQuery?
The solution seems to be using jQuery's contents()
$("#myiframe").contents().find("#myContent")

Related

Making an iframe readonly

In my html I have an Iframe that is a link to a google doc. Currently the user will be able to edit the document. However, I do not want the user to be able to change the document. How would I make the iframe readonly?
Edit
If you are using 'file > publish to web...' in Google Docs, people won't be able to edit your document anyway. Docs Help (see 'How published files look when you share them').
Here's one I just published: try me.
Original Answer
I imagine the only way to fully ensure it's not editable is through some settings on Google Docs itself, any sort of block with JavaScript or CSS has the possibility of being disabled. Also, JavaScript will not be able to control anything inside the iframe, due to it being from a different origin.
With that said, the simplest way is probably with CSS, pointer-events: none; will disable mouse events on the iframe, disabling the user to select it. MDN Docs
iframe { pointer-events: none; }
or as an inline style...
<iframe style='pointer-events: none;'></iframe>
You could use css to cover the iframe with another element/pseudo-element to prevent interaction.
Fiddle
<div class="iframe-wrap">
<iframe src="http://www.yahoo.com" width="300" height="200">
</iframe
</div>
.iframe-wrap {
position: relative;
}
.iframe-wrap::after {
content: "";
display:block;
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
}
There isn't really any way to do this. The browser doesn't recognize the concept of "editing" content in a frame -- all it knows is that it's displaying a page.
If you want to prevent the user from modifying a Google Docs document, use the permissions features provided by Google Docs to prevent editing. The fact that it's in a frame doesn't change anything!

How to remove tumblr controls / buttons / iframe?

I've tried the following codes to remove the controls / buttons / iframe from my Tumblr. None of them seem to work with the new control bar.
#tumblr_controls { display: none;}
<script>
var T_C = document.getElementById('tumblr_controls');
T_C.parentNode.removeChild(T_C);
</script>
I just checked, Tumblr does not seem to be using the id tumblr_controls anymore, that is most probably the reason your code is not working. Try this;
body > iframe:first-child { display: none !important; }
This selector selects any iframe that is the first child directly under body.
If you have some script putting something else in the beginning remove the :first-child (make sure you do not have any other iframe directly under body). Optionally you can use the new class(es) Tumblr is using to select the element you want to hide, but that way when Tumblr changes the class(es) your code will stop working.
An example of how the element in question looks like now:
<iframe class="tmblr-iframe tmblr-iframe--desktop-loggedin-controls iframe-controls--desktop" name="desktop-loggedin-controls" scrolling="no" src="https://www.tumblr.com/dashboard/iframe?tumblelogName=example" width="0" frameborder="0" height="0">
... codes ...
</iframe>
In my tumblr there were two iframes following the body tag... so I made it like this. Hope it helps!
body > iframe:first-child, body > iframe:nth-child(2) {display: none;}
Just wanted to say that yes, it STILL works! I've made a small music player for a notion setup (used Tumblr as a free host) AND I WAS DYINGGGGGG for a solution because body > iframe:first-child { display: none !important; } DID NOT TAKE OFF THE EMBED'S IFRAME!!!! Now my tumblr embed is completely free of it's branding!!!!!!

using iframe as a page overlay dynamically

I have added the following iframe to a page
<iframe src='http://redbug.redrocksoftware.com.au:80/Pages/chamara.html' style="position:absolute;z-index:1;" ></iframe>
chamara.html page contains a button and when I click that button I need the current page to cover up with an overly.
Feedback is the button inside iframe:
When I click it I need something like below to happen.
I have tried with iframe absolute positioning and z-index but couldn't get anything to work yet.
Haha, finally finished the demo! :P
Well, let's go. If you need the iframe cover the whole page only when his button is fired, you can use jQuery to handle the click event. You need use the contents() to get the iframe content, then the find() to get the element that you want. Basically this:
$("#iframe").contents().find("#iframe_button").click(function () {
// Button fired!
})
To the iframe cover all the page I wrote this CSS class:
.iframe_cover {
position:absolute;
top:0;
left:0;
width:100% !important;
height:100% !important;
border:0;
}
So, when the button is fired, the iframe will have this class. Look:
$("#iframe").contents().find("#iframe_button").click(function () {
$("#iframe").addClass("iframe_cover");
})
Demo: http://rafaelalmeida.net78.net/exemplos/soen/29454285-iframe-button/

Mouse/Keybord events full screen html5 video (javascript/jquery)

Is it possible to set onmouseup, onmousedown, onclick etc. functions on a video element that is fullscreen, using webkitRequestFullScreen? I register them for the element when I create it, but I do not appear to get the events when the video is full screen.
Also, is it possible to stop the video progress bar appearing when in full screen mode whenever I move the mouse?
Any answers welcome, either using jquery or javascript, or similar.
I couldn't find a way to listen to mouse events on fullscreen as well,
but I've found a workaround:
Instead of putting the video on fullscreen, I simply change the video CSS to:
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 999;
Video then behaves like it's on fullscreen, and everything works as usual.
Finally found a way to do it in Chrome: wrap your video element with div and call webkitRequestFullScreen() for that div rather then for video + some additional magic will be required.
HTML code snippet:
<div id="video-container" style="background-color: #000000;" onclick=divClicked()>
<video id="myvideo">Video not supported!</video>
</div>
JavaScript code snippet:
function doFullscreen() {
var container = document.getElementById("video-container");
if (container.requestFullscreen) {
container.requestFullscreen();
} else if (container.mozRequestFullScreen) {
container.mozRequestFullScreen();
} else if (container.webkitRequestFullscreen) {
container.webkitRequestFullscreen();
}
var video = document.getElementById("myvideo");
// have to resize the video to fill the whole screen
video.width=window.screen.availWidth;
video.height=window.screen.availHeight;
}
Such approach allows handling mouse/etc. events in div element - see onclick declaration at HTML example above.
Also note that such approach doesn't force video controls to appear either on fullscreen or in windowed mode.
For the second question regarding the progress bar you can add the following to your CSS:
video::-webkit-media-controls-enclosure {
display:none;
}
But note once again that it is not needed when using the approach above.

Hide page until everything is loaded Advanced

I have a webpage which heavily makes use of jQuery.
My goal is to only show the page when everything is ready.
With that I want to avoid showing the annoying page rendering to the user.
I tried this so far (#body_holder is a wrapper inside body):
$(function(){
$('#body_holder').hide();
});
$(window).load(function() {
$("#body_holder").show();
});
This works completely fine, but messes up the layout.
The problem is that hiding the wrapper interferes with the other jQuery functions and plugins used (eg layout-plugin).
So I guess there must be another trick to do this. Maybe lay a picture or div over the body until window.load has occurred?
What approaches do you use?
EDIT:
The solution most likely has to be another way than display:none or hide();
Anything done with jQuery will normally have to wait for document.ready, which is too late IMHO.
Put a div on top, like so:
<div id="cover"></div>
set some styles:
#cover {position: fixed; height: 100%; width: 100%; top:0; left: 0; background: #000; z-index:9999;}
and hide it with JS when all elements are loaded:
$(window).on('load', function() {
$("#cover").hide();
});
Or if for some reason your script uses even longer time then the DOM elements to load, set an interval to check the type of some function that loads the slowest, and remove the cover when all functions are defined!
$(window).on('load', function() {
$("#cover").fadeOut(200);
});
//stackoverflow does not fire the window onload properly, substituted with fake load
function newW()
{
$(window).load();
}
setTimeout(newW, 1000);
#cover {position: fixed; height: 100%; width: 100%; top:0; left: 0; background: #000; z-index:9999;
font-size: 60px; text-align: center; padding-top: 200px; color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li>This</li>
<li>is</li>
<li>a</li>
<li>simple</li>
<li>test</li>
<li>of</li>
<li>a</li>
<li>cover</li>
</ul>
<div id="cover">LOADING</div>
Here is a jQuery solution for those looking:
Hide the body with css then show it after the page is loaded:
CSS:
html { visibility:hidden; }
JavaScript
$(document).ready(function() {
document.getElementsByTagName("html")[0].style.visibility = "visible";
});
The page will go from blank to showing all content when the page is loaded, no flash of content, no watching images load etc.
You should try setting visibility to hidden instead of display:none. Setting visibility to hidden will retain all elements positions and dimensions, thus it shouldn't create layout problems.
Start your HTML with:
<body style="opacity:0;">
At the end of your script:
document.body.style.opacity = 1;
Stumbled upon this and tried #9ete's solution but it didn't help me.
This worked instead:
CSS:
html { visibility:hidden; }
JS:
window.addEventListener('load', function () {
document.getElementsByTagName("html")[0].style.visibility = "visible";
});
As per documentation for window, the load event is fired after all the content (images included) is loaded while $document says that ready is fired after only the DOM is ready.
Your question is valid, but I would not get in a practice of hiding or covering the page while things are spinning up.
It keeps the user from understanding what's happening on the page. While lots of things may need to load, different parts of the page should spring to life as they're loaded. You should get in the practice of locking controls that are not ready, perhaps displaying a spinner or some other progress indicator over them. Or setting the cursor to wait on loading items.
This keeps the user in the loop and allows him to see and interact with parts as they come online instead of obscuring all parts until everything is ready.
You will normally want to load the things the user needs the quickest access to, usually stuff above the fold, first. Loading is a prioritization that can easily be coordinated with Promises.
At the very least seeing the page allows the user to get his bearings and decide what to do. Be transparent.
I was seeking a non-javascript solution so I found one that is working on most browsers in acceptable manner.
Since the loading order of CSS rules matters;
Define the hiding class in the first CSS file or inline in head.
.hidden-onpage-load{ display: none; }
In the body, the class can be used as
<div class="hidden-onpage-load"> ... </div>
Redefine it inline or in a CSS file after all other CSS and JS files are loaded
.hidden-onpage-load{ display: block; }
The simplest solution I've come up with is to wrap the body in a as suggested previously, but set it as hidden from the get go, then use JQuery (or javascript) to unhide on load after all components are loaded.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="bodyDiv" hidden>
Hello World!
</div>
<script>
$(document).ready(function() {
// add JQuery widget loads here
$("#bodyDiv").show(); // reveal complete page
})
</script>
Don't forget, a lot of frameworks use javascript to structure a page. To prevent the page from showing before these modification have been made you'll need to do something like what is described here (e.g. run a script at the end of the page to show the real contents of the page):
Detect if any JavaScript function is running
If you have a div #bodyholder then you can put display:none in your CSS for it and then with jQuery do:
$(document).ready(function() {
$('#body_holder').show();
});
I don't see why hiding a div should interfere with the loading of anything, because all it means is it is hidden. However, if you have lots of jQuery being used then make sure you wrap it in $(document).ready which will make sure that the DOM is fully loaded before the Javascript is executed
A further point is that HTML/CSS is designed for progressive loading, and if you do it properly then you can get a nice progressive loading of content for your users. I personally wouldn't want my users getting a white screen for a few seconds until everything was loaded. Move your Javascript to the end of the page so that it doesn't block loading and get content onto the screen as quickly as possible.

Categories

Resources