Creating a way to navigate back when using jQuery for AJAX - javascript

I am dynamically loading content into part of a page using jQuery .load().
It is working well, but I am having trouble building a way for the user to navigate back to the original content after the new content has been loaded.
I have created a 'close' icon with css which exists on the new page which is loaded, but I am not sure how to set up the jQuery / JavaScript in order for it to navigate the user back to the original state of that part of the page.
This is the relevant js:
// pages to load
var loadLudwig = "lw.html";
$("#work a:first-child").click(function() {
$("#work").fadeTo('slow', 0, function() {
$("#work").load(loadLudwig, function(){
$("#work").fadeTo('slow', 1);
});
});
});
// (& this part is working fine)
The relevant HTML (on the original page) is like this (its a grid of images embedded within anchor tags):
<section id="work">
...img and svg stuff
</section>
I tried many variations of:
$("#close-button").click(function() {
$("#work").fadeTo('slow', 0, function () {
$("#work").load('home.html #work', function() {
$("#work").fadeTo('slow', 1);
});
});
});
but this loads the content very strangely / some of the original functionality of #work is lost.
How do I get my close button to navigate back to the original state of #work?

In the jquery documentation for .load() is stated that:
Script Execution
When calling .load() using a URL without a suffixed selector
expression, the content is passed to .html() prior to scripts being
removed. This executes the script blocks before they are discarded. If
.load() is called with a selector expression appended to the URL,
however, the scripts are stripped out prior to the DOM being updated,
and thus are not executed. An example of both cases can be seen below:
Here, any JavaScript loaded into #a as a part of the document will
successfully execute.
1. $( "#a" ).load( "article.html" );
However, in the following case, script blocks in the document being
loaded into #b are stripped out and not executed:
1. $( "#b" ).load( "article.html #target" );
This is a probable cause for lack of functionality.
I'd also look into event binding. In your code examples you're using .click but if you are loading content or you are creating elements on-the-fly you should be favoring .on(). This method delegates events instead of just binding them to a DOM node.
I'd recommend you reading the whole article.
EDIT:
Here is a quick n'dirty way of achieving the effect
// pages to load
var loadLudwig = "lw.html",
$ludwig,
$work = $('#work'),
$workContent = $work.children(),
$closeButton = $("#close-button");
$work.find('a:first-child').click(function() {
$work.fadeTo('slow', 0, function() {
//Here is the tricky part
//Detaching keeps all the jQuery data on the elements
$workContent.detach();
//The first time, load the content,
//if the content is already loaded
//append it to the container
if(!$ludwig){
$work.load(loadLudwig, function(){
//Save the content in a var
//so you can reuse it later
$ludwig = $work.children();
$work.fadeTo('slow', 1);
});
} else {
$ludwig.appendTo($work);
$work.fadeTo('slow', 1);
}
});
});
$closeButton.click(function() {
$work.fadeTo('slow', 0, function () {
//Remove the old content, don't worry
//because is stored in $ludwig
$work.children().detach();
//Instead of reloading the content, just
//attach the fragment again
$workContent.appentTo($work);
$work.fadeTo('slow', 1);
});
});

You probably need to save the html somewhere. For example:
// Top of file
var oldHTML = "";
// Lots of stuff...
$("#work a:first-child").click(function() {
$("#work").fadeTo('slow', 0, function() {
// Store the old html
oldHTML = $("#work").html();
$("#work").load(loadLudwig, function(){
$("#work").fadeTo('slow', 1);
});
});
});
// Code for the close button
$("#close-button").click(function() {
$("#work").fadeTo('slow', 0, function () {
$("#work").html(oldHTML).fadeIn("slow");
});
});
Alternatively, instead of replacing the html, you could create another child. Of course, you might have to slightly change your markup.
<section id="work">
<div id="oldHTML">
...img and svg stuff
</div>
<div id="newSection" style="display:none;">
</div>
</section>
Then replace $("#work") with $("#oldHTML") in your first piece of code like so:
$("#oldHTML a:first-child").click(function() {
$("#oldHTML").fadeTo('slow', 0, function() {
$("#oldHTML").hide();
$("#newSection").load(loadLudwig, function(){
$("#newSection").show().fadeTo('slow', 1);
});
});
});
// Code for the close button
$("#close-button").click(function() {
$("#newSection").fadeTo('slow', 0, function () {
$("#newSection").hide();
$("#work").fadeIn("slow");
});
});

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>

jquery click-function is executed when page loads but not when clicked

I use jQuery to get the height of a div #img-copyright when the page is loaded, write in the var copyrightHeight and set the height of the div to 0.
When a different div is clicked, the function showImgCopyright() should set the max-height of the div #img-copyright to the content of the var.
I made two tries.
First one:
var copyrightHeight;
$(document).ready(function () {
copyrightHeight = $("#img-copyright").height();
console.log(copyrightHeight);
// just used to see if the height got written in the var - it is
$("img-copyright").css("max-height", 0);
$("#show-img-copyright").click(showImgCopyright());
function showImgCopyright() {
$("#img-copyright").css("max-height", copyrightHeight);
}
});
Second one:
var copyrightHeight;
$(document).ready(function () {
copyrightHeight = $("#img-copyright").height();
console.log(copyrightHeight);
// just used to see if the height got written in the var - it is
$("img-copyright").css("max-height", 0);
$("#show-img-copyright").click(function (){
$("#img-copyright").css("max-height", copyrightHeight);
});
});
In the first example the function is directly executed after the page is loaded and NOT when clicking the div (not the way I wanted it to be).
In the second example it works as I wanted it - the function just is executed when clicking the div.
But I don't get why.
How can I make it work with an extra function like in the first example?
Thank you very much.
I also found out, I forgot a # in the line $("img-copyright").css("max-height", 0);.
So the right code would be:
var copyrightHeight;
$(document).ready(function () {
copyrightHeight = $("#img-copyright").height();
$("#img-copyright").css("max-height", 0);
$("#show-img-copyright").click(showImgCopyright);
function showImgCopyright() {
$("#img-copyright").css("max-height", copyrightHeight);
}
});

How to add translate="no" via JS to a dynamic translation script?

I have a script on my website that translates the text contained within a span when the user mouses over an anchor, and it works just fine. However, browsers that do auto-translation seem to be grabbing the titles that get generated onmouseover and translating them as well, which defeats the purpose of the script. I have tried adding the property translate="no" to the generated text using JS (as seen below in Line 10) but I must be missing something, because it doesn't seem to be having an effect.
Please help?
JS:
$.each($("li"), function(i, elements) {
var links = elements.getElementsByTagName("a");
var article_title = elements.getElementsByClassName("article-title")[0];
$.each(links, function(j, link) {
var previous_title = article_title.innerHTML;
if (!$(link).is('.newspaper, .doi')) {
link.addEventListener("mouseover", function() {
$(article_title).fadeTo(150, 0.5, function() {
article_title.innerHTML = link.title;
$(article_title).prop('translate', 'no');
$(article_title).fadeTo(150, 1, function() {});
});
});
link.addEventListener("mouseout", function() {
$(article_title).fadeTo(150, 0.5, function() {
article_title.innerHTML = previous_title;
$(article_title).fadeTo(150, 1, function() {});
});
});
}
});
});
});
HTML:
<li>
[EN]
[ES]
<span class="article-title">This is an example</span>
</li>
First, are you sure that the script interprets
translate="no"
Property correctly? As in, it figures that this should not be translated? Maybe the code logic appears to be the culprit.
Second, try using .attr instead of .prop?

Where do I put $(this) in the function?

Since I want to use classes instead of id's in these functions(I have three of the same function with different things I want to .append) I am sure I need to put $(this) in those functions somewhere to only trigger only ONE function on button click and not all three of them. but I am not sure because I am a total beginner in jquery/js, so I would appreciate some help.
$(document).ready(function () {
$(".onclick").click(function () {
$('#favorites').append('<div data-role="main"class="ui-content"><div class="ui-grid-b"><div class="ui-block-a">Arrow</div><div class="ui-block-b">More Info</div><div class="ui-block-c">Unfavorite</div></div></div>');
});
});
http://codepen.io/anon/pen/JYxqEw - HTML And the Jquery Code
$('.onclick') selects all the elements with a class of onclick. That means that, whenever something with class="onclick" is clicked, that function will fire.
If you want all of those elements to append that exact HTML to the #favorites element, then you can leave your code as-is.
However, if what you're trying to do is append that html to the clicked element, that is when you'd use $(this) -- that selects the element you clicked with jQuery, then you can append directly to that element ie:
$(document).ready(function () {
$(".onclick").click(function () {
// this will append the HTML to the element that triggered the click event.
$(this).append('<div data-role="main"class="ui-content"><div class="ui-grid-b"><div class="ui-block-a">Arrow</div><div class="ui-block-b">More Info</div><div class="ui-block-c">Unfavorite</div></div></div>');
});
});
EDIT
so to insert the contents of each .onclick into #favorites, you'll need to use the innerHTML value of the DOM node. example fiddle:
http://jsbin.com/qazepubuzu/edit?html,js,output
When you select something with jQuery, you're actually getting back not just the DOM node, but a jQuery object -- this object contains both a reference to the actual DOM node ([0]), as well as a jquery object ([1]).
So to select the DOM node with $(this), you target the node: $(this)[0]. Then you can use .innerHTML() to grab the HTML contents of the node and do as you like.
Final result:
$(function () {
$('.onclick').click(function () {
$('#favorites').append( $(this)[0].innerHTML );
});
});
So the building blocks are not that complex, but I think you're a novice jQuery developer and so you may not be clear on the difference between jQuery and JS yet.
$(selector, context) allows us to create a jQuery collection for a CSS selector which is the child of a current context DOM node, though if you do not specify one there is an automatic one (which is document.body, I think). Various functions iterating over jQuery collections make the particular element available as this within the JavaScript. To get to the strong element from the .onclick element in the HTML fragment you need to travel up in the hierarchy, then to the appropriate element. Then, we can collect the text from the element. We can do this in either JS or jQuery.
To do this with simply jQuery:
// AP style title case, because Chicago is too crazy.
var to_title_case = (function () { // variable scope bracket
var lower_case = /\b(?:a|an|the|and|for|in|so|nor|to|at|of|up|but|on|yet|by|or)\b/i,
first_word = /^(\W*)(\w*)/,
last_word = /(\w*)(\W*)$/;
function capitalize(word) {
return word.slice(0, 1).toUpperCase() + word.slice(1).toLowerCase();
}
function capitalize_mid(word) {
return lower_case.exec(word) ? word.toLowerCase() : capitalize(word);
}
return function to_title_case(str) {
var prefix = first_word.exec(str),
str_minus_prefix = str.slice(prefix[0].length),
suffix = last_word.exec(str_minus_prefix),
center = str_minus_prefix.slice(0, -suffix[0].length);
return prefix[1] + capitalize(prefix[2]) + center.replace(/\w+/g, capitalize_mid)
+ capitalize(suffix[1]) + suffix[2];
};
})();
$(document).ready(function() {
$(".onclick").click(function () {
var text = $(this).parents('.ui-grid-a').find('.ui-block-a').text();
var html = '<div data-role="main"class="ui-content">'
+ '<div class="ui-grid-b"><div class="ui-block-a">'
+ to_title_case(text) + '</div><div class="ui-block-b">More Info</div>'
+ '<div class="ui-block-c">Unfavorite</div></div></div>';
$("#favorites").append(html);
});
});

how to repeat same Javascript code over multiple html elements

Note: Changed code so that images and texts are links.
Basically, I have 3 pictures all with the same class, different ID. I have a javascript code which I want to apply to all three pictures, except, the code needs to be SLIGHTLY different depending on the picture. Here is the html:
<div class=column1of4>
<img src="images/actual.jpg" id="first">
<div id="firsttext" class="spanlink"><p>lots of text</p></div>
</div>
<div class=column1of4>
<img src="images/fake.jpg" id="second">
<div id="moretext" class="spanlink"><p>more text</p></div>
</div>
<div class=column1of4>
<img src="images/real.jpg" id="eighth">
<div id="evenmoretext" class="spanlink"><p>even more text</p></div>
</div>
Here is the Javascript for the id="firsttext":
$('#firstextt').hide();
$('#first, #firsttext').hover(function(){
//in
$('#firsttext').show();
},function(){
//out
$('#firsttext').hide();
});
So when a user hovers over #first, #firsttext will appear. Then, I want it so that when a user hovers over #second, #moretext should appear, etc.
I've done programming in Python, I created a sudo code and basically it is this.
text = [#firsttext, #moretext, #evenmoretext]
picture = [#first, #second, #eighth]
for number in range.len(text) //over here, basically find out how many elements are in text
$('text[number]').hide();
$('text[number], picture[number]').hover(function(){
//in
$('text[number]').show();
},function(){
//out
$('text[number]').hide();
});
The syntax is probably way off, but that's just the sudo code. Can anyone help me make the actual Javascript code for it?
try this
$(".column1of4").hover(function(){
$(".spanlink").hide();
$(this).find(".spanlink").show();
});
Why not
$('.spanlink').hide();
$('.column1of4').hover(
function() {
// in
$(this).children('.spanlink').show();
},
function() {
// out
$(this).children('.spanlink').hide();
}
);
It doesn't even need the ids.
You can do it :
$('.column1of4').click(function(){
$(this); // the current object
$(this).children('img'); // img in the current object
});
or a loop :
$('.column1of4').each(function(){
...
});
Dont use Id as $('#id') for multiple events, use a .class or an [attribute] do this.
If you're using jQuery, this is quite easy to accomplish:
$('.column1of4 .spanlink').hide();
$('.column1of4 img').mouseenter(function(e){
e.stopPropagation();
$(this).parent().find('.spanlink').show();
});
$('.column1of4 img').mouseleave(function(e){
e.stopPropagation();
$(this).parent().find('.spanlink').hide();
});
Depending on your markup structure, you could use DOM traversing functions like .filter(), .find(), .next() to get to your selected node.
$(".column1of4").hover(function(){
$(".spanlink").hide();
$(this).find(".spanlink, img").show();
});
So, the way you would do this, given your html would look like:
$('.column1of4').on('mouseenter mouseleave', 'img, .spanlink', function(ev) {
$(ev.delegateTarget).find('.spanlink').toggle(ev.type === 'mouseenter');
}).find('.spanlink').hide();
But building on what you have:
var text = ['#firsttext', '#moretext', '#evenmoretext'];
var picture = ['#first', '#second', '#third'];
This is a traditional loop using a closure (it's better to define the function outside of the loop, but I'm going to leave it there for this):
// You could also do var length = text.length and replace the "3"
for ( var i = 0; i < 3; ++i ) {
// create a closure so that i isn't incremented when the event happens.
(function(i) {
$(text[i]).hide();
$([text[i], picture[i]].join(',')).hover(function() {
$(text[i]).show();
}, function() {
$(text[i]).hide();
});
})(i);
}
And the following is using $.each to iterate over the group.
$.each(text, function(i) {
$(text[i]).hide();
$([text[i], picture[i]].join(', ')).hover(function() {
$(text[i]).show();
}, function() {
$(text[i]).hide();
});
});
Here's a fiddle with all three versions. Just uncomment the one you want to test and give it a go.
I moved the image inside the div and used this code, a working example:
$('.column1of4').each(function(){
$('div', $(this)).each(function(){
$(this).hover(
function(){
//in
$('img', $(this)).show();
},
function(){
//out
$('img', $(this)).hide();
});
});
});
The general idea is 1) use a selector that isn't an ID so I can iterate over several elements without worrying if future elements will be added later 2) locate the div to hide/show based on location relational to $(this) (will only work if you repeat this structure in your markup) 3) move the image tag inside the div (if you don't, then the hover gets a little spazzy because the positioned is changed when the image is shown, therefore affecting whether the cursor is inside the div or not.
EDIT
Updated fiddle for additional requirements (see comments).

Categories

Resources