Reinstatiating javascript for image crop - javascript

I'm trying to cobble together a function for a user to select an image for their avatar, preview it on the page using javascript, select the crop using the jquery guillotine, then upload it to the server w/ the coordinates where it can be processed.
So far I can select an image to upload and it will appear in the preview, but guillotine needs the image to be already loaded when it is invoked. Is there a way that I can force guillotine to re-load when I select an image?
This is my code:
<head>
<script src="{% static "assets/js/user_profile.js" %}"></script>
<script type="text/javascript">
function PreviewImage() {
var oFReader = new FileReader();
oFReader.readAsDataURL(document.getElementById("id_avatar").files[0]);
oFReader.onload = function (oFREvent) {
document.getElementById("avatar_preview").src = oFREvent.target.result;
};
};
</script>
</head>
<body>
<input type='file' id='id_avatar' name='avatar' onchange="PreviewImage();" /><br />
<div id="parent" style="width: 300px; height: 300px; overflow: hidden;">
<img id="avatar_preview" src="#" alt="your image" style="width:400px;" />
</div>
</body>
And this is what's in my user_profile.js, which is what I'd like to reinstantiate when I change the avatar input:
jQuery(function() {
var picture = $('#avatar_preview')
var camelize = function() {
var regex = /[\W_]+(.)/g
var replacer = function (match, submatch) { return submatch.toUpperCase() }
return function (str) { return str.replace(regex, replacer) }
}()
var showData = function (data) {
data.scale = parseFloat(data.scale.toFixed(4))
for(var k in data) { $('#'+k).html(data[k]) }
}
picture.on('load', function() {
picture.guillotine({ eventOnChange: 'guillotinechange' })
picture.guillotine('fit')
for (var i=0; i<5; i++) { picture.guillotine('zoomIn') }
// Show controls and data
$('.loading').remove()
$('.notice, #controls, #data').removeClass('hidden')
showData( picture.guillotine('getData') )
// Bind actions
$('#controls a').click(function(e) {
e.preventDefault()
action = camelize(this.id)
picture.guillotine(action)
})
// Update data on change
picture.on('guillotinechange', function(e, data, action) { showData(data) })
})
// Display random picture
picture.attr('src', 'img/unsplash.com_' + Math.ceil(Math.random() * 25) + '.jpg')
})
Is there a way to wrap that into something that can be reloaded without reloading the page and losing the preview?

With a few modifications you can achieve what you want. First off, Guillotine's code demo is much easier to follow than the code from the display demo.
Whenever you set a preview (change the src attribute) the image will be loaded and an onload event will be triggered (eventually). You only care about when new previews finish loading, you don't need to worry about changes on the file input.
So, focus on reloading the plugin each time the image finishes loading, like this. Basically it boils down to:
picture.on('load', function() {
// Reload the plugin (remove existing instance if any and create a new one)
if (picture.guillotine('instance')) picture.guillotine('remove')
picture.guillotine({ eventOnChange: 'guillotinechange' })
// Bind buttons, only once! (to avoid overlaps)
if (! picture.data('bindedBtns')) {
picture.data('bindedBtns', true)
$('#rotate_left').click(function(){ picture.guillotine('rotateLeft') })
$('#rotate_right').click(function(){ picture.guillotine('rotateRight') })
// ...
}
}
You might also find Presto quite useful. It's sole purpose is to display image previews from file inputs. It gracefully falls back looking for the best available way to display the previews.
If you also pair it up with Bifrost the last attempt will be to upload the image asynchronously and get the preview from the server (no need for HTML5, XMLHttpRequest or Flash) so you can be sure you'll get a preview on any browser.
Unfortunately I haven't had the time to complete Presto's readme but the source is very clean and at the top you'll find documentation for it's API and features.
Hope it helps.

Related

Javascript function works on html onclick but doesn't work html onload [duplicate]

How do you add an onload event to an element?
Can I use:
<div onload="oQuickReply.swap();" ></div>
for this?
No, you can't. The easiest way to make it work would be to put the function call directly after the element
Example:
...
<div id="somid">Some content</div>
<script type="text/javascript">
oQuickReply.swap('somid');
</script>
...
or - even better - just in front of </body>:
...
<script type="text/javascript">
oQuickReply.swap('somid');
</script>
</body>
...so it doesn't block the following content from loading.
You can trigger some js automatically on an IMG element using onerror, and no src.
<img src onerror='alert()'>
The onload event can only be used on the document(body) itself, frames, images, and scripts. In other words, it can be attached to only body and/or each external resource. The div is not an external resource and it's loaded as part of the body, so the onload event doesn't apply there.
onload event it only supports with few tags like listed below.
<body>, <frame>, <iframe>, <img>, <input type="image">, <link>, <script>, <style>
Here the reference for onload event
Try this! And never use trigger twice on div!
You can define function to call before the div tag.
$(function(){
$('div[onload]').trigger('onload');
});
DEMO: jsfiddle
I just want to add here that if any one want to call a function on load event of div & you don't want to use jQuery(due to conflict as in my case) then simply call a function after all the html code or any other code you have written including the function code and
simply call a function .
/* All Other Code*/
-----
------
/* ----At the end ---- */
<script type="text/javascript">
function_name();
</script>
OR
/* All Other Code*/
-----
------
/* ----At the end ---- */
<script type="text/javascript">
function my_func(){
function definition;
}
my_func();
</script>
I needed to have some initialization code run after a chunk of html (template instance) was inserted, and of course I didn't have access to the code that manipulates the template and modifies the DOM. The same idea holds for any partial modification of the DOM by insertion of an html element, usually a <div>.
Some time ago, I did a hack with the onload event of a nearly invisible <img> contained in a <div>, but discovered that a scoped, empty style will also do:
<div .... >
<style scoped="scoped" onload="dosomethingto(this.parentElement);" > </style>
.....
</div>
Update(Jul 15 2017) -
The <style> onload is not supported in last version of IE. Edge does support it, but some users see this as a different browser and stick with IE. The <img> element seems to work better across all browsers.
<div...>
<img onLoad="dosomthing(this.parentElement);" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" />
...
</div>
To minimize the visual impact and resource usage of the image, use an inline src that keeps it small and transparent.
One comment I feel I need to make about using a <script>is how much harder it is to determine which <div> the script is near, especially in templating where you can't have an identical id in each instance that the template generates. I thought the answer might be document.currentScript, but this is not universally supported. A <script> element cannot determine its own DOM location reliably; a reference to 'this' points to the main window, and is of no help.
I believe it is necessary to settle for using an <img> element, despite being goofy. This might be a hole in the DOM/javascript framework that could use plugging.
Avoid using any interval-based methods (as they are not performant and accurate) and use MutationObserver targeting a parent div of dynamically loaded div for better efficiency.
Update: Here's a handy function I wrote. Use it like this:
onElementLoaded("div.some_class").then(()=>{}).catch(()=>{});
/**
*
* Wait for an HTML element to be loaded like `div`, `span`, `img`, etc.
* ex: `onElementLoaded("div.some_class").then(()=>{}).catch(()=>{})`
* #param {*} elementToObserve wait for this element to load
* #param {*} parentStaticElement (optional) if parent element is not passed then `document` is used
* #return {*} Promise - return promise when `elementToObserve` is loaded
*/
function onElementLoaded(elementToObserve, parentStaticElement) {
const promise = new Promise((resolve, reject) => {
try {
if (document.querySelector(elementToObserve)) {
console.log(`element already present: ${elementToObserve}`);
resolve(true);
return;
}
const parentElement = parentStaticElement
? document.querySelector(parentStaticElement)
: document;
const observer = new MutationObserver((mutationList, obsrvr) => {
const divToCheck = document.querySelector(elementToObserve);
if (divToCheck) {
console.log(`element loaded: ${elementToObserve}`);
obsrvr.disconnect(); // stop observing
resolve(true);
}
});
// start observing for dynamic div
observer.observe(parentElement, {
childList: true,
subtree: true,
});
} catch (e) {
console.log(e);
reject(Error("some issue... promise rejected"));
}
});
return promise;
}
Implementation details:
HTML:
<div class="parent-static-div">
<div class="dynamic-loaded-div">
this div is loaded after DOM ready event
</div>
</div>
JS:
var observer = new MutationObserver(function (mutationList, obsrvr) {
var div_to_check = document.querySelector(".dynamic-loaded-div"); //get div by class
// var div_to_check = document.getElementById('div-id'); //get div by id
console.log("checking for div...");
if (div_to_check) {
console.log("div is loaded now"); // DO YOUR STUFF!
obsrvr.disconnect(); // stop observing
return;
}
});
var parentElement = document.querySelector("parent-static-div"); // use parent div which is already present in DOM to maximise efficiency
// var parentElement = document // if not sure about parent div then just use whole 'document'
// start observing for dynamic div
observer.observe(parentElement, {
// for properties details: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit
childList: true,
subtree: true,
});
we can use MutationObserver to solve the problem in efficient way adding a sample code below
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
#second{
position: absolute;
width: 100px;
height: 100px;
background-color: #a1a1a1;
}
</style>
</head>
<body>
<div id="first"></div>
<script>
var callthis = function(element){
element.setAttribute("tabIndex",0);
element.focus();
element.onkeydown = handler;
function handler(){
alert("called")
}
}
var observer = new WebKitMutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
for (var i = 0; i < mutation.addedNodes.length; i++)
if(mutation.addedNodes[i].id === "second"){
callthis(mutation.addedNodes[i]);
}
})
});
observer.observe(document.getElementById("first"), { childList: true });
var ele = document.createElement('div');
ele.id = "second"
document.getElementById("first").appendChild(ele);
</script>
</body>
</html>
In November 2019, I am seeking a way to create a (hypothetical) onparse EventListener for <elements> which don't take onload.
The (hypothetical) onparse EventListener must be able to listen for when an element is parsed.
Third Attempt (and Definitive Solution)
I was pretty happy with the Second Attempt below, but it just struck me that I can make the code shorter and simpler, by creating a tailor-made event:
let parseEvent = new Event('parse');
This is the best solution yet.
The example below:
Creates a tailor-made parse Event
Declares a function (which can be run at window.onload or any time) which:
Finds any elements in the document which include the attribute data-onparse
Attaches the parse EventListener to each of those elements
Dispatches the parse Event to each of those elements to execute the Callback
Working Example:
// Create (homemade) parse event
let parseEvent = new Event('parse');
// Create Initialising Function which can be run at any time
const initialiseParseableElements = () => {
// Get all the elements which need to respond to an onparse event
let elementsWithParseEventListener = document.querySelectorAll('[data-onparse]');
// Attach Event Listeners and Dispatch Events
elementsWithParseEventListener.forEach((elementWithParseEventListener) => {
elementWithParseEventListener.addEventListener('parse', updateParseEventTarget, false);
elementWithParseEventListener.dataset.onparsed = elementWithParseEventListener.dataset.onparse;
elementWithParseEventListener.removeAttribute('data-onparse');
elementWithParseEventListener.dispatchEvent(parseEvent);
});
}
// Callback function for the Parse Event Listener
const updateParseEventTarget = (e) => {
switch (e.target.dataset.onparsed) {
case ('update-1') : e.target.textContent = 'My First Updated Heading'; break;
case ('update-2') : e.target.textContent = 'My Second Updated Heading'; break;
case ('update-3') : e.target.textContent = 'My Third Updated Heading'; break;
case ('run-oQuickReply.swap()') : e.target.innerHTML = 'This <code><div></code> is now loaded and the function <code>oQuickReply.swap()</code> will run...'; break;
}
}
// Run Initialising Function
initialiseParseableElements();
let dynamicHeading = document.createElement('h3');
dynamicHeading.textContent = 'Heading Text';
dynamicHeading.dataset.onparse = 'update-3';
setTimeout(() => {
// Add new element to page after time delay
document.body.appendChild(dynamicHeading);
// Re-run Initialising Function
initialiseParseableElements();
}, 3000);
div {
width: 300px;
height: 40px;
padding: 12px;
border: 1px solid rgb(191, 191, 191);
}
h3 {
position: absolute;
top: 0;
right: 0;
}
<h2 data-onparse="update-1">My Heading</h2>
<h2 data-onparse="update-2">My Heading</h2>
<div data-onparse="run-oQuickReply.swap()">
This div hasn't yet loaded and nothing will happen.
</div>
Second Attempt
The First Attempt below (based on #JohnWilliams' brilliant Empty Image Hack) used a hardcoded <img /> and worked.
I thought it ought to be possible to remove the hardcoded <img /> entirely and only dynamically insert it after detecting, in an element which needed to fire an onparse event, an attribute like:
data-onparse="run-oQuickReply.swap()"
It turns out, this works very well indeed.
The example below:
Finds any elements in the document which include the attribute data-onparse
Dynamically generates an <img src /> and appends it to the document, immediately after each of those elements
Fires the onerror EventListener when the rendering engine parses each <img src />
Executes the Callback and removes that dynamically generated <img src /> from the document
Working Example:
// Get all the elements which need to respond to an onparse event
let elementsWithParseEventListener = document.querySelectorAll('[data-onparse]');
// Dynamically create and position an empty <img> after each of those elements
elementsWithParseEventListener.forEach((elementWithParseEventListener) => {
let emptyImage = document.createElement('img');
emptyImage.src = '';
elementWithParseEventListener.parentNode.insertBefore(emptyImage, elementWithParseEventListener.nextElementSibling);
});
// Get all the empty images
let parseEventTriggers = document.querySelectorAll('img[src=""]');
// Callback function for the EventListener below
const updateParseEventTarget = (e) => {
let parseEventTarget = e.target.previousElementSibling;
switch (parseEventTarget.dataset.onparse) {
case ('update-1') : parseEventTarget.textContent = 'My First Updated Heading'; break;
case ('update-2') : parseEventTarget.textContent = 'My Second Updated Heading'; break;
case ('run-oQuickReply.swap()') : parseEventTarget.innerHTML = 'This <code><div></code> is now loaded and the function <code>oQuickReply.swap()</code> will run...'; break;
}
// Remove empty image
e.target.remove();
}
// Add onerror EventListener to all the empty images
parseEventTriggers.forEach((parseEventTrigger) => {
parseEventTrigger.addEventListener('error', updateParseEventTarget, false);
});
div {
width: 300px;
height: 40px;
padding: 12px;
border: 1px solid rgb(191, 191, 191);
}
<h2 data-onparse="update-1">My Heading</h2>
<h2 data-onparse="update-2">My Heading</h2>
<div data-onparse="run-oQuickReply.swap()">
This div hasn't yet loaded and nothing will happen.
</div>
First Attempt
I can build on #JohnWilliams' <img src> hack (on this page, from 2017) - which is, so far, the best approach I have come across.
The example below:
Fires the onerror EventListener when the rendering engine parses <img src />
Executes the Callback and removes the <img src /> from the document
Working Example:
let myHeadingLoadEventTrigger = document.getElementById('my-heading-load-event-trigger');
const updateHeading = (e) => {
let myHeading = e.target.previousElementSibling;
if (true) { // <= CONDITION HERE
myHeading.textContent = 'My Updated Heading';
}
// Modern alternative to document.body.removeChild(e.target);
e.target.remove();
}
myHeadingLoadEventTrigger.addEventListener('error', updateHeading, false);
<h2>My Heading</h2>
<img id="my-heading-load-event-trigger" src />
use an iframe and hide it iframe works like a body tag
<!DOCTYPE html>
<html>
<body>
<iframe style="display:none" onload="myFunction()" src="http://www.w3schools.com"></iframe>
<p id="demo"></p>
<script>
function myFunction() {
document.getElementById("demo").innerHTML = "Iframe is loaded.";
}
</script>
</body>
</html>
Since the onload event is only supported on a few elements, you have to use an alternate method.
You can use a MutationObserver for this:
const trackElement = element => {
let present = false;
const checkIfPresent = () => {
if (document.body.contains(element)) {
if (!present) {
console.log('in DOM:', element);
}
present = true;
} else if (present) {
present = false;
console.log('Not in DOM');
}
};
const observer = new MutationObserver(checkIfPresent);
observer.observe(document.body, { childList: true });
checkIfPresent();
return observer;
};
const element = document.querySelector('#element');
const add = () => document.body.appendChild(element);
const remove = () => element.remove();
trackElement(element);
<button onclick="add()">Add</button>
<button onclick="remove()">Remove</button>
<div id="element">Element</div>
we can use all these tags with onload
<body>, <frame>, <frameset>, <iframe>, <img>, <input type="image">, <link>, <script> and <style>
eg:
function loadImage() {
alert("Image is loaded");
}
<img src="https://www.w3schools.com/tags/w3html.gif" onload="loadImage()" width="100" height="132">
I really like the YUI3 library for this sort of thing.
<div id="mydiv"> ... </div>
<script>
YUI().use('node-base', function(Y) {
Y.on("available", someFunction, '#mydiv')
})
See: http://developer.yahoo.com/yui/3/event/#onavailable
This is very simple solution and 100% working.
Just load an <img> tag inside the div or at last line of div, if you think you want to execute javascript, after loading all data in div.
As <img> tag supports onload event, so you can easily call javascript here like below:
<div>
<img onLoad="alert('Problem Solved');" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" />
</div>
This above image will show only a single Dot(.), which you even cant see normally.
Try it.
First to answer your question: No, you can't, not directly like you wanted to do so.
May be a bit late to answer, but this is my solution, without jQuery, pure javascript.
It was originally written to apply a resize function to textareas after DOM is loaded and on keyup.
Same way you could use it to do something with (all) divs or only one, if specified, like so:
document.addEventListener("DOMContentLoaded", function() {
var divs = document.querySelectorAll('div'); // all divs
var mydiv = document.getElementById('myDiv'); // only div#myDiv
divs.forEach( div => {
do_something_with_all_divs(div);
});
do_something_with_mydiv(mydiv);
});
If you really need to do something with a div, loaded after the DOM is loaded, e.g. after an ajax call, you could use a very helpful hack, which is easy to understand an you'll find it ...working-with-elements-before-the-dom-is-ready.... It says "before the DOM is ready" but it works brillant the same way, after an ajax insertion or js-appendChild-whatever of a div. Here's the code, with some tiny changes to my needs.
css
.loaded { // I use only class loaded instead of a nodename
animation-name: nodeReady;
animation-duration: 0.001s;
}
#keyframes nodeReady {
from { clip: rect(1px, auto, auto, auto); }
to { clip: rect(0px, auto, auto, auto); }
}
javascript
document.addEventListener("animationstart", function(event) {
var e = event || window.event;
if (e.animationName == "nodeReady") {
e.target.classList.remove('loaded');
do_something_else();
}
}, false);
I am learning javascript and jquery and was going through all the answer,
i faced same issue when calling javascript function for loading div element.
I tried $('<divid>').ready(function(){alert('test'}) and it worked for me. I want to know is this good way to perform onload call on div element in the way i did using jquery selector.
thanks
As all said, you cannot use onLoad event on a DIV instead but it before body tag.
but in case you have one footer file and include it in many pages. it's better to check first if the div you want is on that page displayed, so the code doesn't executed in the pages that doesn't contain that DIV to make it load faster and save some time for your application.
so you will need to give that DIV an ID and do:
var myElem = document.getElementById('myElementId');
if (myElem !== null){ put your code here}
I had the same question and was trying to get a Div to load a scroll script, using onload or load. The problem I found was that it would always work before the Div could open, not during or after, so it wouldn't really work.
Then I came up with this as a work around.
<body>
<span onmouseover="window.scrollTo(0, document.body.scrollHeight);"
onmouseout="window.scrollTo(0, document.body.scrollHeight);">
<div id="">
</div>
Link to open Div
</span>
</body>
I placed the Div inside a Span and gave the Span two events, a mouseover and a mouseout. Then below that Div, I placed a link to open the Div, and gave that link an event for onclick. All events the exact same, to make the page scroll down to bottom of page. Now when the button to open the Div is clicked, the page will jump down part way, and the Div will open above the button, causing the mouseover and mouseout events to help push the scroll down script. Then any movement of the mouse at that point will push the script one last time.
You could use an interval to check for it until it loads like this:
https://codepen.io/pager/pen/MBgGGM
let checkonloadDoSomething = setInterval(() => {
let onloadDoSomething = document.getElementById("onloadDoSomething");
if (onloadDoSomething) {
onloadDoSomething.innerHTML="Loaded"
clearInterval(checkonloadDoSomething);
} else {`enter code here`
console.log("Waiting for onloadDoSomething to load");
}
}, 100);
When you load some html from server and insert it into DOM tree you can use DOMSubtreeModified however it is deprecated - so you can use MutationObserver or just detect new content inside loadElement function directly so you will don't need to wait for DOM events
var ignoreFirst=0;
var observer = (new MutationObserver((m, ob)=>
{
if(ignoreFirst++>0) {
console.log('Element add on', new Date());
}
}
)).observe(content, {childList: true, subtree:true });
// simulate element loading
var tmp=1;
function loadElement(name) {
setTimeout(()=>{
console.log(`Element ${name} loaded`)
content.innerHTML += `<div>My name is ${name}</div>`;
},1500*tmp++)
};
loadElement('Michael');
loadElement('Madonna');
loadElement('Shakira');
<div id="content"><div>
You can attach an event listener as below. It will trigger whenever the div having selector #my-id loads completely to DOM.
$(document).on('EventName', '#my-id', function() {
// do something
});
Inthis case EventName may be 'load' or 'click'
https://api.jquery.com/on/#on-events-selector-data-handler
Here is a trick that worked for me,
you just need to put your div inside a body element
<body>
<!-- Some code here -->
<body onload="alert('Hello World')">
<div ></div>
</body>
<!-- other lines of code -->
</body>
Use the body.onload event instead, either via attribute (<body onload="myFn()"> ...) or by binding an event in Javascript. This is extremely common with jQuery:
$(document).ready(function() {
doSomething($('#myDiv'));
});
You cannot add event onload on div, but you can add onkeydown and trigger onkeydown event on document load
$(function ()
{
$(".ccsdvCotentPS").trigger("onkeydown");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<div onkeydown="setCss( );"> </div>`
Try this.
document.getElementById("div").onload = alert("This is a div.");
<div id="div">Hello World</div>
Try this one too. You need to remove . from oQuickReply.swap() to make the function working.
document.getElementById("div").onload = oQuickReplyswap();
function oQuickReplyswap() {
alert("Hello World");
}
<div id="div"></div>

Set iFrame source and reload with jQuery

I have a unique issue that--while I've seen similar questions and answers--none quite address my challenge.
Currently, I provide a "print" button that loads the print dialog on a browser based on an embedded and hidden iframe. This works just fine, but I don't want to slow down page loading by pulling in the iframe for a large PDF.
So, I want to load an iframe without the source, then write the proper source url if the user clicks the print icon, then reload the iframe, and finally, show the dialog box.
Unfortunately, the print dialog pops up before I can reload the iframe so loads a blank page in the dialog box. On subsequent clicks, the PDF is loaded and ready for print.
<a href='#' id='load_pdf' ><i class='fa fa-2 fa-print'></i></a>
<iframe id="iFramePdf" src="" style="display:none;"></iframe>
<script type="text/javascript">
jQuery(document).ready(function() {
$("#load_pdf").click(loadPDF);
function loadPDF() {
$('#iFramePdf').attr('src', "my.pdf");
// Attempt to reload iframe
$('#iFramePdf').load("my.pdf");
sendPrint('iFramePdf')
}
function sendPrint(elementId) {
var iframe = $(element_id)[0];
iframe.contentWindow.focus();
iframe.contentWindow.print();
}
});
</script>
I've tried the following various methods to reload:
// Attempt 1
$('#iFramePdf').attr('src', function () { return
$(this).contents().get(0).location.href });
// Attempt 2
$('#iFramePdf').attr("src", $('#iFramePdf').attr("src"));
$('#iFramePdf').attr('src', function () { return $(this).contents().get(0).location.href });
// Attempt 3
$('#iFramePdf')[0].contentWindow.location.reload(true);
// Attempt 4
var getMyFrame = document.getElementById(elementId);
getMyFrame.contentWindow.location.reload(true);
I've even tried using jQuery's defer method, but had no luck with that (possibly because I'm lacking knowledge). If I could get any guidance, I'd appreciate it.
try to change this:
function loadPDF() {
$('#iFramePdf').attr('src', "my.pdf");
// Attempt to reload iframe
$('#iFramePdf').load("my.pdf");
sendPrint('iFramePdf')
}
to something like this:
function loadPDF() {
$('#iFramePdf').attr('src', "my.pdf");
}
$('#iFramePdf').load(function(){
sendPrint('iFramePdf')
})
it should work
You can try .promise(). For obvious reasons I can't test it out, but I think 3 seconds should be adequate for the iframe to load. Be aware that this is as syntactically correct as I can get it without testing it out. Adjust the fadeIn(1800) and the delay(1200) accordingly.
HTML
<a href='#' id='load_pdf' ><i class='fa fa-2 fa-print'></i></a>
<p id="msg" style="display: none;">Printing Document...</p>
<div id="printPort" style="opacity: 0; width: 1px; height: 1px;"></div>
jQuery
$(function() {
$("#load_pdf").on('click', loadPDF('my.pdf'));
// Create the iframe, and put it inside #printPort
// Change it's src to the file argument
// Animate the #msg for 3 seconds
var loadPDF = function(file) {
$('<iframe id="iFramePdf" src="blank.html"></iframe>').appendTo("#printPort");
$("#iFramePdf").att('src', file);
return $('#msg').fadeIn(1800).delay(1200).fadeOut();
}
var sendPrint = function(elementId) {
var iframe = $(element_id)[0];
iframe.contentWindow.focus();
iframe.contentWindow.print();
}
// Once the animation is done the promise will resolve and sendPrint will execute on callback.
$.when(loadPDF).done(sendPrint('iFramePdf'));
});

Revert to original image after jquery hover better way?

to replace images on hover i have used jquery:
<script type='text/javascript'>
$(document).ready(function(){
var blog1 = $(".blogimage1").attr('src');
$(".imghover").hover(function() {
$(this).attr("src","images/imghover.png");
}, function() {
$(this).attr("src",blog1);
});
});
</script>
here is the html:
<a href="blog-inner.html" title="read more">
<img src="images/blogpost4.jpg" alt="blog post title" class="img-responsive imghover blogimage1">
</a>
and it works exactly like i want it to, however i dont know how many blog images there will be so for now i would have to add in blogimage1, blogImage2, etc into the html and do the same with jquery. is there a way i can do this without having to store each original blog image and write the same function a million times?
Try this : You can save previous image in blog1 variable when mouse hover and replace it back when mouse leave.
$(document).ready(function(){
var blog1 = '';
$(".imghover").hover(function() {
//save previous image in variable
blog1 = $(this).attr('src');
$(this).attr("src","images/imghover.png");
}, function() {
$(this).attr("src",blog1);
});
});
Use .data() to store original image path.
Store arbitrary data associated with the matched elements or return the value at the named data store for the first element in the set of matched elements.
code
$(".imghover").hover(function() {
$(this).data('orgimage', this.src); //Store data
this.src = "images/imghover.png";
}, function() {
this.src = $(this).data('orgimage'); //Retrieve and set original image path
});

windows 8 javascript app print fragment doesnt print picture from a <div>

I have this problem: ( i will attach code below ) I have a split screen template windows 8 app. In the right side of the screen I have a recipe with a picture in the top part. and a description in lower part. Both these 2 parts are in the same block . The picture and the text are shown from an array in data.js file. For example the picture is shown from var background:"images\recipes\picture1.jpg" and the description from var description:"example text bla bla bla". I create a document fragment that i clone and send it to print. Everything prints right, except the PICTURE. I get an X icon instead of the picture. Now I will write all the code I use for this. I have no ideea what is wrong. Everything is right in an example I follow. There it works, mine not.
Ready function add-ons:
document.getElementById("Print").addEventListener("click", PrintButtonHandler, false);
// Register for Print Contract
registerForPrintContract();
All code regarding printing:
function registerForPrintContract() {
var printManager = Windows.Graphics.Printing.PrintManager.getForCurrentView();
printManager.onprinttaskrequested = onPrintTaskRequested;
WinJS.log && WinJS.log("Print Contract registered. Use Print button to print.", "sample", "status");
}
/// <summary>
/// Print event handler for printing via the PrintManager API. The user has to manually invoke
/// the print charm after this function is executed.
/// </summary>
/// <param name="printEvent" type="Windows.Graphics.Printing.PrintTaskRequest">
/// The event containing the print task request object.
/// </param>
function onPrintTaskRequested(printEvent) {
var printTask = printEvent.request.createPrintTask("Print part", function (args) {
var frag = document.createDocumentFragment();
frag.appendChild(document.getElementById("print").cloneNode(true));
args.setSource(MSApp.getHtmlPrintDocumentSource(frag));
// Register the handler for print task completion event
printTask.oncompleted = onPrintTaskCompleted;
});
}
/// <summary>
/// Print Task event handler is invoked when the print job is completed.
/// </summary>
/// <param name="printTaskCompletionEvent" type="Windows.Graphics.Printing.PrintTaskCompleted">
/// The event containing the print task completion object.
/// </param>
function onPrintTaskCompleted(printTaskCompletionEvent) {
// Notify the user about the failure
if (printTaskCompletionEvent.completion === Windows.Graphics.Printing.PrintTaskCompletion.failed) {
WinJS.log && WinJS.log("Failed to print.", "sample", "error");
}
}
function PrintButtonHandler() {
// Optionally, functions to be executed immediately before and after printing can be configured as following:
window.document.body.onbeforeprint = beforePrint;
window.document.body.onafterprint = afterPrint;
// If the print contract is registered, the print experience is invoked.
Windows.Graphics.Printing.PrintManager.showPrintUIAsync();
}
var page = WinJS.UI.Pages.define("/page/split.html", {
ready: function (element, options) {
var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();
dataTransferManager.addEventListener("datarequested", dataRequested);
document.getElementById("share").addEventListener("click", showShareUI, false);
},
unload: function () {
var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();
dataTransferManager.removeEventListener("datarequested", dataRequested);
}
});
function dataRequested(e) {
var request = e.request;
// Title is required
var dataPackageTitle = document.getElementById("titluReteta").value;
if ((typeof dataPackageTitle === "string") && (dataPackageTitle !== "")) {
var range = document.createRange();
range.selectNode(document.getElementById("print"));
request.data = MSApp.createDataPackage(range);
request.data.properties.title = dataPackageTitle;
// The HTML fragment we are using has an image tag that references a local file accessible only to this application.
// To make sure that target application can render this image, we need to populate a resourceMap as part of the share operation data
// We use the image's relative src property as the key to the resourceMap item we're adding
var path = document.getElementById("print").getAttribute("src");
var imageUri = new Windows.Foundation.Uri(path);
var streamReference = Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(imageUri);
request.data.resourceMap[path] = streamReference;
} else {
request.failWithDisplayText(SdkSample.missingTitleError);
}
}
function showShareUI() {
Windows.ApplicationModel.DataTransfer.DataTransferManager.showShareUI();
}
})();
This the code from the page:
</header>
<img class="article-image" src="#" data-win-bind="src: backgroundImage; alt: title" style="border: 10px double #73513B;" />
<div class="article-content" data-win-bind="innerHTML: content"> </div>
</article>
</div>
And the data-win-bind is the picture that doesnt print.
I added this line <link rel="stylesheet" type="text/css" href="/css/print.css" media="print" /> and print.css contains this:
#rootGrid
{
width: 100%;
height: 100%;
display: block;
}
#inputLabel, #outputLabel, #input, #statusMessage
{
display: none;
}
.article
{
border:none;
}
I really need a fast answer if anyone can solve this. I need this project to be send until Friday. And I am clueless, after lots of example I tried to follow. Thank you very much to the guy that will save me!
LE: I tried also a classic inside the description field. The picture appear in the app, but the same result for printing: a big X icon instead of picture.
Resolved by printing entire document with reformating CSS code for showing just what I want to show. Now it captures all pictures with no problem. No answer got for the initial problem with capturing only the picture.

Tracking which image in a list of images is clicked?

I have a set of images that correspond to video thumbnails. The user clicks a thumb which loads the browser. This would be simple enough, but I need to track which of the thumbs was clicked, so that I can automatically cue up the next video in sequence.
My first thought was to do something like this (highly simplified example):
<div class="thumbs">
<img id="vt_0" src="thumbxxx00.jpg" />
<img id="vt_1" src="thumbxxx01.jpg" />
<img id="vt_2" src="thumbxxx02.jpg" />
<img id="vt_3" src="thumbxxx03.jpg" />
<img id="vt_4" src="thumbxxx04.jpg" />
<img id="vt_5" src="thumbxxx05.jpg" />
<img id="vt_6" src="thumbxxx06.jpg" />
</div>
<script type="text/javascript">
var videos = [ "xxx00", "xxx01", "xxx02", "xxx03", "xxx04", "xxx05", "xxx06" ];
var video_index = null;
function playVideo(id) {
// play video then call "onVideoFinish()" when video ends.
}
function onVideoFinish() {
video_index = (video_index = 6) ? video_index : video_index+1;
playVideo(videos[video_index]);
}
$j("div.thumbnail img").live("click", function (e) {
e.preventDefault();
var selected_id = $(this).attr("id").split("_")[1];
video_index = selected_id;
playvideo( videos[video_index] );
});
</script>
At first glance this seems to be okay, but I'm not sure if this is the best/most elegant solution, especially as I'd be implementing all these methods from within an object context.
This is how I would do it. The only global that you need in this case is currentPlayOrder, which could be stored someone as part of a preferences or configuration model.
First the HTML. I moved the video sources into the rel attribute of the associated thumbnail. I assume that your application is generating the thumbnails, in which case, this would be an appropriate method since whatever generates the thumbnail HTML could be made aware of the associated video sources.
<div class="thumbs">
<img id="vt_0" src="http://stackoverflow.com/content/img/so/logo.png" rel="videoA"/>
<img id="vt_1" src="http://serverfault.com/content/img/sf/logo.png" rel="videoB"/>
<img id="vt_2" src="http://stackoverflow.com/content/img/so/logo.png" rel="videoC"/>
<img id="vt_3" src="http://serverfault.com/content/img/sf/logo.png" rel="videoD"/>
<img id="vt_4" src="http://stackoverflow.com/content/img/so/logo.png" rel="videoE"/>
<img id="vt_5" src="http://serverfault.com/content/img/sf/logo.png" rel="videoF"/>
<img id="vt_6" src="http://stackoverflow.com/content/img/so/logo.png" rel="videoG"/>
</div>
Now the JS. Notice the use of previousSibling and nextSibling to determine play order:
<script type="text/javascript">
var PLAY_ORDER_BACKWARD = "previousSibling";
var PLAY_ORDER_FORWARD = "nextSibling";
var currentPlayOrder = PLAY_ORDER_FORWARD;
$(document).ready(function() {
$(".thumbs img").each(function(i, node) {
$(node).click(function() {
playVideo(this.getAttribute("rel"), this);
});
});
});
var playVideo = function(source, thumbNode) {
console.log("Play video %s", source);
onVideoFinish(thumbNode);
// If your video play accepts a callback, you may need to pass it as
// function() { onVideoFinish(thumbNode); }
}
var onVideoFinish = function(thumbNode) {
// Get the next img node (if any) in the appropriate direction
while ( thumbNode = thumbNode[currentPlayOrder] ) {
if ( thumbNode.tagName == "IMG" ) { break; }
}
// If an img node exists and it has the rel (video source) attribute
if ( thumbNode && thumbNode.getAttribute("rel") ) {
playVideo(thumbNode.getAttribute("rel"), thumbNode);
}
// Otherwise, assume that there are no more thumbs/videos in this direction
else {
console.log("No more videos to play");
}
}
</script>
Hope that helps.
Here's how I would do it.
Instead of storing the video names inside an array, why not store the video name along with the thumbnail?
You can use the class attribute to store the name of the video.
Once you take this approach, things become simple.
<div class="thumbs">
<img id="vt_0" src="thumbxxx00.jpg" class="xxx00"/>
<img id="vt_1" src="thumbxxx01.jpg" class="xxx01"/>
<img id="vt_2" src="thumbxxx02.jpg" class="xxx02"/>
<img id="vt_3" src="thumbxxx03.jpg" class="xxx03"/>
<img id="vt_4" src="thumbxxx04.jpg" class="xxx04"/>
<img id="vt_5" src="thumbxxx05.jpg" class="xxx05"/>
<img id="vt_6" src="thumbxxx06.jpg" class="xxx06"/>
</div>
<script type="text/javascript">
function setupVideoPlayer(order)
{
//lastThumb won't be accessible from outside of setupVideoPlayer
//function.
var lastThumb = null;
var imageSelector = 'div.thumbs img';
function playVideo(video)
{
//Play the video.
onVideoFinish();
}
function onVideoFinish()
{
//If order is 'ascending', we will go to the 'next'
//image, otherwise we will go to 'previous' image.
var method = order == 'asc' ? 'next' : 'prev';
//When user is at the end, we need to reset it either at the
//first image (for ascending) or the last (for descending).
var resetIndex = order == 'asc' ? 0 : $(imageSelector).length - 1;
//When video has finished playing, we will try to
//find the next/prev (depending upon order) sibling of 'lastThumb',
//If we can not find any sibling, it means we are at the
//last/first thumbnail and we will go back and fetch the first/last
//image.
//Also, instead of calling the playVideo method, we will
//fire the click event of thumbnail. This way, if you decide to
//do something in future (say playing an ad before the video)
//you only need to do it in your click handler.
if($(lastThumb)[method]().length == 0)
$(imageSelector).get(resetIndex).click();
else
$(lastThumb)[method]().click();
}
$j(imageSelector)
.click(
function()
{
//on click, we store the reference to the thumbnail which was
//clicked.
lastThumb = this;
//We get the name of the video from the class attribute
//and play the video.
playVideo($(this).attr('class'));
}
);
}
$(document).ready(
function() { setupVideoPlayer('asc'); }
);
</script>
Above code has the advantage that you can modify your HTML and it will automatically play those videos.
You can wrap the images with an anchor tag and use the onClick method as follows:
<img src="thumbxxx00.jpg" />
<img src="thumbxxx01.jpg" />
...

Categories

Resources