Attach An Element When A PDF href Is Opened - javascript

Am testing something, and am not entirely sure it's possible. I have a basic href for an external pdf. I would like to attach a dynamic element to it, say a div and h1 tag for now.
View
<script>
function createElements(){
var div = $(document.createElement('div'));
div.innerHTML = '<h1 id="myTitle" class="back-button" alt="custom-title">';
$('#myTitle').css({
'position': 'absolute',
'z-index': '99',
'top': '16px',
'left': '12px',
'width': '11%',
});
}
</script>
Basically, when the external href is opened, I want to add attach an h1 tag on that document. Not sure if that's possible, however, testing the waters for now. The code above doesn't seem to work, but would appreciate feedback to see if this can be done with plain vanilla javascript/jquery.

You cannot affect a document that is not yet opened. For this to work, your javascript code would need to be inside the PDF but since browsers treat PDF content differently (as they should), it will never be executed. In short, I don't think this is possible.

Your href will always send the user to a PDF-viewer of the browser and you'll lose control over that.
If you want to have an element visible above or over the PDF file, you can maybe use a "template page" where you have your HTML element and a fullscreen iFrame with a src that points to the PDF file.
This will render the browser's PDF viewer in that iFrame winthin your template page.
Ex.
<div>
<div>
<!-- Your element here (you can make this absolute to make it lay over the pdf file etc.. -->
</div>
<iframe src=".../.pdf" style="width:100vw;height:100vh">
</div>

Maybe you don't need jQuery at all. I would do something like this (notice I leave the div empty beforehand):
View
<div id="myDiv"></div>
function createElements(){
var text = document.createElement("h1");
text.innerHTML ="MY heading";
document.getElementById("myDiv").appendChild(text);
}

Related

Sort iframes without reloading in Angular [duplicate]

Take a look at this simple HTML:
<div id="wrap1">
<iframe id="iframe1"></iframe>
</div>
<div id="warp2">
<iframe id="iframe2"></iframe>
</div>
Let's say I wanted to move the wraps so that the #wrap2 would be before the #wrap1. The iframes are polluted by JavaScript. I am aware of jQuery's .insertAfter() and .insertBefore(). However, when I use those, the iFrame loses all of its HTML, and JavaScript variables and events.
Lets say the following was the iFrame's HTML:
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
// The variable below would change on click
// This represents changes on variables after the code is loaded
// These changes should remain after the iFrame is moved
variableThatChanges = false;
$(function(){
$("body").click(function(){
variableThatChanges = true;
});
});
</script>
</head>
<body>
<div id='anything'>Illustrative Example</div>
</body>
</html>
In the above code, the variable variableThatChanges would...change if the user clicked on the body. This variable, and the click event, should remain after the iFrame is moved (along with any other variables/events that have been started)
My question is the following: with JavaScript (with or without jQuery), how can I move the wrap nodes in the DOM (and their iframe childs) so that the iFrame's window stays the same, and the iFrame's events/variables/etc stay the same?
It isn't possible to move an iframe from one place in the dom to another without it reloading.
Here is an example to show that even using native JavaScript the iFrames still reload:
http://jsfiddle.net/pZ23B/
var wrap1 = document.getElementById('wrap1');
var wrap2 = document.getElementById('wrap2');
setTimeout(function(){
document.getElementsByTagName('body')[0].appendChild(wrap1);
},10000);
This answer is related to the bounty by #djechlin
A lot of search on the w3/dom specs and didn't find anything final that specifically says that iframe should be reloaded while moving in the DOM tree, however I did find lots of references and comments in the webkit's trac/bugzilla/microsoft regarding different behavior changes over the years.
I hope someone will find anything specific regarding this issue, but for now here are my findings:
According to Ryosuke Niwa - "That's the expected behavior".
There was a "magic iframe" (webkit, 2010), but it was removed in 2012.
According to MS - "iframe resources are freed when removed from the DOM". When you appendChild(node) of existing node - that node is first removed from the dom.
Interesting thing here - IE<=8 didn't reload the iframe - this behavior is (somewhat) new (since IE>=9).
According to Hallvord R. M. Steen comment, this is a quote from the iframe specs
When an iframe element is inserted into a document that has a browsing context, the user agent must create a new browsing context, set the element's nested browsing context to the newly-created browsing context, and then process the iframe attributes for the "first time".
This is the most close thing I found in the specs, however it's still require some interpretation (since when we move the iframe element in the DOM we don't really do a full remove, even if the browsers uses the node.removeChild method).
Whenever an iframe is appended and has a src attribute applied it fires a load action similarly to when creating an Image tag via JS. So when you remove and then append them they are completely new entities and they refresh. Its kind of how window.location = window.location will reload a page.
The only way I know to reposition iframes is via CSS. Here is an example I put together showing one way to handle this with flex-box:
https://jsfiddle.net/3g73sz3k/15/
The basic idea is to create a flex-box wrapper and then define an specific order for the iframes using the order attribute on each iframe wrapper.
<style>
.container{
display: flex;
flex-direction: column;
}
</style>
<div class="container">
<div id="wrap1" style="order: 0" class="iframe-wrapper">
<iframe id="iframe1" src="https://google.com"></iframe>
</div>
<div id="warp2" style="order: 1" class="iframe-wrapper">
<iframe id="iframe2" src="https://bing.com"></iframe>
</div>
</div>
As you can see in the JS fiddle these order styles are inline to simplify the flip button so rotate the iframes.
I sourced the solution from this StackOverflow question: Swap DIV position with CSS only
Hope that helps.
If you have created the iFrame on the page and simply need to move it's position later try this approach:
Append the iFrame to the body and use a high z-index and top,left,width,height to put the iFrame where you want.
Even CSS zoom works on the body without reloading which is awesome!
I maintain two states for my "widget" and it is either injected in place in the DOM or to the body using this method.
This is useful when other content or libraries will squish or squash your iFrame.
BOOM!
Unfortunately, the parentNode property of an HTML DOM element is read-only. You can adjust the positions of the iframes, of course, but you can't change their location in the DOM and preserve their states.
See this jsfiddle I created that provides a good test bed. http://jsfiddle.net/RpHTj/1/
Click on the box to toggle the value. Click on the "move" to run the javascript.
This question is pretty old... but I did find a way to move an iframe without it reloading. CSS only. I have multiple iframes with camera streams, I dont like when they reload when i swap them. So i used a combination of float, position:absolute, and some dummy blocks to move them around without reloading them and having the desired layout on demand (resizing and all).
If you are using the iframe to access pages you control, you could create some javascript to allow your parent to communicate with the iframe via postMessage
From there, you could build login inside the iframe to record state changes, and before moving dom, request that as a json object.
Once moved, the iframe will reload, you can pass the state data into the iframe and the iframe listening can parse the data back into the previous state.
PaulSCoder has the right solution. Never manipulate the DOM for this purpose. The classic approach for this is to have a relative position and "flip" the positions in the click event. It's only not wise to put the click event on the body, because it bubbles from other elements too.
$("body").click(function () {
var frame1Height = $(frame1).outerHeight(true);
var frame2Height = $(frame2).outerHeight(true);
var pos = $(frame1).css("top");
if (pos === "0px") {
$(frame1).css("top", frame2Height);
$(frame2).css("top", -frame1Height);
} else {
$(frame1).css("top", 0);
$(frame2).css("top", 0);
}
});
If you only have content that is not cross-domain you could save and restore the HTML:
var htmlContent = $(frame).contents().find("html").children();
// do something
$(frame).contents().find("html").html(htmlContent);
The advantage of the first method is, that the frame keeps on doing what it was doing. With the second method, the frame gets reloaded and starts it's code again.
At least in some circumstances a shadow dom with slotting might be an option.
<template>
<style>div {outline:1px solid black; height:45px}</style>
<div><slot name="a" /></div>
<div><slot name="b" /></div>
</template>
<div id="shadowhost">
<iframe src="data:text/html,<button onclick='this.innerText+=`!`'>!</button>"
slot="a" height=40px ></iframe>
</div>
<button onclick="ifr.slot= (ifr.slot=='a') ? 'b' : 'a';">swap</button>
<script>
document.querySelector('#shadowhost').attachShadow({mode: 'open'}).appendChild(
document.querySelector('template').content
);
ifr=document.querySelector('iframe');
</script>
In response to the bounty #djechlin placed on this question, I have forked the jsfiddle posted by #matt-h and have come to the conclusion that this is still not possible.
http://jsfiddle.net/gr3wo9u6/
//this does not work, the frames reload when appended back to the DOM
function swapFrames() {
var w1 = document.getElementById('wrap1');
var w2 = document.getElementById('wrap2');
var f1 = w1.querySelector('iframe');
var f2 = w2.querySelector('iframe');
w1.removeChild(f1);
w2.removeChild(f2);
w1.appendChild(f2);
w2.appendChild(f1);
//f1.parentNode = w2;
//f2.parentNode = w1;
//alert(f1.parentNode.id);
}

How to place dom element in HTML without rendering it?

I need to place html/javascript code in html page that I don't want to render/run at page load.
I want to get this content later with `innerHTML' and use it dynamical.
How can code be saved in html page so that browsers ignore it but it can be manipulated with Javascript dom interaction.
<script norun="true" type="text/xml">
<script type="text/javascript"></script>
<div>html</div>
</script>
Above code is not working, because closing tag of inner <script> tag closes the parent "text/xml" type script. Need corss-platform method to keep JS/HTML inside dormant and intact.
Future solution: HTML5 <template>. But it's not supported on IE
Safe solution: entity-escape or base64 encode and decode in javascript
Hacky: <svg style="display:none;"><![CDATA[ your inert content here ]]></svg>, since html5 itself does not allow cdata but an exception is made for foreign content, i.e. svg and mathml
When I do a similar thing (usually with view fragments for SPA-style pages) I generally go with the script tag approach similar to what you were doing. This is assuming I'm using Hogan.js but you can ignore those details for the example:
<script type="text/hogan-template" id="tweet-template">
<div class="tweet">
<div class="username">{{username}}</div>
<div class="body">{{body}}</div>
<div class="date-posted">{{posted}}</div>
</div>
</script>
From here you can fetch it via JavaScript when you need it and the browser ignores it as HTML.
var tweetTemplateEl = document.querySelector("#tweet-template"),
tweetTemplate = hogan.compile(tweetTemplateEl.innerHTML);
var tweetList = document.querySelector("#tweet-list"),
tweetItem = document.createElement("li");
tweetItem.innerHTML = tweetTemplate.render(tweetData);
tweetList.appendChild(tweetItem);
For JavaScript, you could use something like a placeholder on the page. I'm not really sure the most semantic tag to use so I'll use div as it's generally a go to "default" tag. So, in place of where you'd place an include you could simply do:
<div class="script-placeholder" id="some_js_file_name" data-href="/js/some_js_file_name.js"></div>
This could be used in multiple ways but here's one option:
window.require = function(fileName) {
var body = document.querySelector("body"),
placeholder = document.querySelector(["#", fileName].join("")),
src = placeholder.dataset.href,
script = document.createElement("script");
script.src = src;
body.appendChild(script);
};
Which you can then add to whatever you'd like to initiate a require:
someElement.addEventListener("click", function(e) {
require("some_js_file_name");
});
That might be something that allows you to achieve what you'd like to achieve.
NOTE: It's important to note that if you really want to go the dynamic load route you should probably invest in an established library to accomplish this like CommonJS if you'd like the style of requires like I've shown here. This handwritten sample is just that, it's a sample to give you an idea of what is going on.
Wrap the code in an HTML comment: <!-- ... -->
Browsers will not parse or render anything inside of the comment.
When you want to initiate rendering, uncomment the code. This can be done by wrapping the comment in an identifiable element, getting its innerHTML, stripping out the comment syntax, and resetting the innerHTML of the element to be the live uncommented markup.
http://jsfiddle.net/92du461p/2/
<button id="b">Show hidden content</button>
<div id="delay-render"><!-- <p>hide me</p> --></div>
<script>
var r = document.getElementById('delay-render');
var b = document.getElementById('b');
b.addEventListener('click', function() {
r.innerHTML = r.innerHTML.match(/^<!--(.*)-->$/)[1]
});
</script>

jQuery HTML editor

For my current project i am creating a html editor.
How its needs to work
Elements Inside
Text Area - To type the HTML as text
Iframe - To show the typed HTML as real [rendering the string HTML to UI]
Some Buttons
Working Logic
A registered user typing something inside the text area :
ex :
<div style="border:1px solid red;">This is a div</div>
after that user clicks on a button [Converting to UI],so that we need to change the iframe content to the new value [value of text area]
after converting the iframe elements html will be
<html>
<head>
<style>
.mydiv{
}
</style>
</head>
<body>
<div class="mydiv" style="color:red">This is a div</div>
</body>
</html>
There is another button that which give back the iframe HTML to text area ,
All these works good [No big problems now except the firebug issue],But i need to integrate a better UI to customize the iframe content - >
ex : User clicks on a DIV on iframe ,so that time a pop up will arise to change the color and font of that div [it will be some color picker for choosing color and drop down for to choose font][i need to implement some more like this]. hope that it will not be a big pain.
So after that i need to get the modified value.
Ex: i changed the color of a div ,
so the returned value will be something like this
<html>
<head></head>
<body>
<div class="mydiv" style="color:gray;">Hello World !</div>
</body>
</html>
TO DO
Please note the style attribute [above ] ,its in inline style ,i
need to convert it into the class scope if the element have a class
defined
so i need to add/update the css class "mydiv" with new style's .
Assume that we are changing something on the body element of iframe ,body is a common element so i need to add/update the BODY scope in the css style block
ex:
BODY{
color:gray;
}
I hope that you guys got my idea,i need to implement something like this on my current project.
Is there anything slimier this ? [so that no need to worry ,i can use that]
or
How can i achieve this ? especially the grouping of css class.
I hopes that i need to use some kind of regular expressions ,but i am very weak on this.
Please help me to complete.
What i tried is here : http://jsfiddle.net/5PKXq/3/
Thank you.
Much as I think you're really reinventing the wheel here, I don't see what's keeping you from getting the contents of the textarea, and then just appending it directly to, I don't know, a container div (it doesn't even have to be an iframe, which I personally think is a bad way to go).
var $textarea = $('textarea'),
$container = $('div#container'),
$refresh = $('button#refresh'), // or something
;
$refresh.on('click', function () {
$container.empty()
.html($textarea.val())
;
// or something
});
Do note that that's untested code.

How to make images clickable in javascript?

I recently setup custom rotational banners on my blogger using this code I come across but I can't seem to figure out how to make the images clickable to link to the homepage.
Any help would be much appreciated.
Heres the code:
<script type='text/javascript'>
var HeaderImage= new Array()
HeaderImage[0]="http://Example1.png"
HeaderImage[1]="http://Example2.png"
HeaderImage[2]="http://Example3.png"
HeaderImage[3]="http://Example4.png"
HeaderImage[4]="http://Example5.gif"
HeaderImage[5]="http://Example6.png"
HeaderImage[6]="http://Example7.png"
var random=Math.round(6*Math.random());
document.write("<style>");
document.write("#header {");
document.write(' background:url("' + HeaderImage[random] + '") no-repeat left TOP;');
document.write(" }");
document.write("</style>");
</script>
Its working now guys.
I just wasn't sure exactly where to put the tags everyone was teling me.
Thanks very much for all your help.
This code has issues with &quot instead of ". But aside from that, what this code is doing is setting the background image for an object with id="header". To make that object clickable, you can surround the header object with an <a> tag. For example, if the header object was a div, then you would use something like this:
<div id="header"></a>
If there's some reason why you don't want to use a link to make the area clickable (which is the simplest way to do it), then you could also use javascript like this:
document.getElementById("header").onclick = function() {
window.location = "http://my.example.com";
}
This would either be placed after the page HTML (so the object in question is already loaded when this code runs).
If you show us the actual HTML that includes the header object, we could be more specific about how to make it clickable.
From reviewing your HTML, if you want to make it clickable with just your HTML, you can change this part of your HTML:
<b:section class='header' id='header' maxwidgets='2' showaddelement='yes'>
<b:widget id='Header1' locked='true' title='Mum4d.com (Header)' type='Header'/>
</b:section>
to this (which just surrounds it with an <a> tag:
<a href="http://my.example.com">
<b:section class='header' id='header' maxwidgets='2' showaddelement='yes'>
<b:widget id='Header1' locked='true' title='Mum4d.com (Header)' type='Header'/>
</b:section>
</a>
Well, you don't actually have any image elements, so that's your first problem.
The simplest solution (to make images clickable) is to wrap images in anchor tags with the href attribute set to your index. What it seems like you're actually doing is dynamically writing some css for an element with id #header and setting its background to the image. When you do this, there are no actual img elements, so there's nothing for a user to click on other than the element itself.
Without seeing any more of your markup, I'd suggest just wrapping your #header element in an anchor like this <a href='/'><some_element id='header'></some_element></a>
Idk how Blogger works, so I'll just tell you the quick and dirty way to get it working with javascript.
Put this after the code you showed us, even after the closing script tag
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script>
$(function() {
$('#header').click(function() {
window.location = '/';
});
});
</script>

Manipulating <body> with jQuery? (Or figuring a better solution)

I'm trying to create a JS-script to make modifications to add a footer to HTML -documents on the fly. The idea is to append a div-element at the end of the document to contain the footer, and to provide a floating fixed footer, I also need to have all of the other content wrapped in a div, basically I need something like this:
<html>
<head>
<title>Foobar</title>
</head>
<body>
<div id="contentWrapper">
<!-- Content is here -->
</div>
<div id="footerWrapper">
<!-- Footer goes here -->
</div>
</body>
</html>
The problem is, that the HTML is generated from a system where the end user's have had a little too much control over the structure (it's a blogging platform), and there's no guarantee of a certain sturcture hence I need to wrap the content in a div to ensure the footer works ok.
What I tried, and realized that doesn't work is:
$(document.body).wrap($('<div/>').attr('id','footerWrapper'));
The problem with this is that due to the fact that the HTML structure is generated by the user, I have been forced to inject links to the JS-file inside the <body>-tag. So now when I call wrap(), it seems that everything is first removed from $(document.body) and then appended in the new div. Since the JS-files are linked from inside , calling wrap() seems to remove them momentarily, and it seems that the scripts are unloaded by the browser and everything stops working and I'm left with a blank page. Not exactly what I had in mind.
Next idea was to first copy the JS-tags to the head-element to preserve them, so I wrapped them in a div (yeah, ugly, I know), and tried to copy them to the :
$(document.head).append($('#copyToHead').html());
That didn't do anything, and seems that $(document.head) isn't usable with functions such as .html() and .append().
So, now I'm out of ideas. Anyone have any ideas?
$(document.head) isn't usable with functions such as .html() and .append().
That would be because document.head is undefined
Use $("head")[0]
not clear on what your are trying to add to the head part. if you are simply trying to add a div to the end here is a solution:
$(document).ready(function(){
$(document.body).append($('<div></div>').attr('id','mydiv').html('This is footer'));
});
idea
If leave fact, that $(document.body) doesn't exist, wrapping everything into div and then setting id through attr might be problematic (don't ask me why—it just happens). So I played with it and created this little snippet (with preview, 100% working).
Since you can't play with html, but can "append" script I did whole document manipulation through inline script.
code
<script type="text/javascript">
$(document).ready(function(){
$("body")
.wrapInner('<div id="wrapper"/>')
.append('<div id="footer">footer text</div>');
});
</script>
preview
http://jsbin.com/ezoqo4/3
edits:
further simplification and proper markup generation
I believe this should serve you better:
$('body')
.children ().wrapAll ($('<div/>').attr('id','contentWrapper'))
.end ()
.append ($('<div/>').attr('id','footerWrapper'))
;
Ref: wrapAll

Categories

Resources