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

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?

Related

jQuery text change from HTML range slider

I'm new at jQuery, so I expect there is an easy answer.
I have a JSON file with different text strings for different dates. I also have an html range slider that I uses the <datalist> tag to define specific dates on the slider. I have written a $.getJSON function that nests a $.each() function to pull the strings from the JSON file.
I need to write in the functionality to display different strings based on the slider position.
This is my jQuery:
var location = $('#state-dates')[0];
$(document).on('input', '#state-dates', function() {
if (location === 1911) {
$.getJSON('Arizona.json', function(inputOne){
$.each(inputOne.first, function(i, field){
$("#leg-control").html(field.legControl);
});
});
}
else if (location === 1943) {
$.getJSON('Arizona.json', function(inputTwo){
$.each(inputTwo.second, function(i, field){
$("#leg-control").html(field.legControl);
});
});
}
});
And my HTML:
<input type="range" min="1911" max="2013" class="bar" step=".1" list="date-list" value="1911" id="state-dates">
Is there a different jQuery method that I should be using to detect the change in the slider, and so display the new string? I also realize that I should probably use < or > instead of = since I want the same text to only change when it reaches a new defined position. Thank you!
EDIT
To help clarify, I'm adding in the relevant JSON and HTML.
JSON:
{
"first": [
{
"legControl": "Not recorded",
}],
"second": [
{
"leg-control": "Democratic",
}]
}
And the HTML for entering the text:
<div class="json-text">
<p class="fill-in" id="leg-control"></p>
</div>
I was able to work out a solution with a web developer friend of mine, so in case anyone else stumbles across this question, the solution I used:
//call the JSON file and store it as a variable called jdata
$.getJSON('Arizona.json', function(json) {
jdata = json;
});
var slider = $('#sliderValue')[0];
slider.oninput = function() {
var position = this.value;
var jrows = $(jdata).filter(function (i, n) {
return n.sYear <= position && n.eYear > position;
});
$("#year-start").html(jrows[0].jsonLineOne);
$("#year-end").html(jrows[0].jsonLineTwo);
};
Essentially this takes the slider input, and runs a return command to check the position. If it is within the bounds of one subsection of the JSON file, then that section is pulled. Hopefully this helps anyone else who comes across it in the future.

Loop through element and change based on link attribute

Trying to figure this out. I am inexperienced at jQuery, and not understanding how to loop through elements and match one.
I have 3 divs:
<div class="first-image">
<img src="images/first.png">
</div>
<div class="second-image">
<img src="images/second.png">
</div>
<div class="third-image">
<img src="images/third.png">
</div>
And off to the side, links in a div named 'copy' with rel = first-image, etc.:
...
Clicking the link will fade up the image in the associated div (using GSAP TweenMax)
Here is the function I've been working on to do this... but I am not fully understanding how to loop through all the "rel" elements, and make a match to the one that has been clicked on.
<script>
//pause slideshow on members to ledger when text is clicked, and show associated image
$(function() {
$('.copy').on('click','a',function(e) {
e.preventDefault();
var slideName = $(this).attr('rel');
$("rel").each(function(i){
if (this.rel == slideName) {
console.log(this);
}
});
//var change_screens_tween = TweenMax.to('.'+slideName+'', 1, {
//autoAlpha:1
//});
});
});
</script>
What am I doing wrong? I don't even get an error in my browser. :-(
Thanks to the answer below, I got farther. Here is my revised code.
$('[rel]').each(function(k, v){
if (v == slideName) {
var change_screens_tween = TweenMax.to('.'+slideName+'', 1, {
autoAlpha:1
});
} else {
var change_screens_tween = TweenMax.to('.'+slideName+'', 1, {
autoAlpha:0
});
}
});
});
This is starting to work, but makes the screenshots appear and then instantly fade out. And it only works once. Any thoughts?
Add brackets around rel, like so:
$('[rel]').each(function() {
if ($(this).attr('rel') == slideName) {
console.log(this);
}
});

Creating a way to navigate back when using jQuery for AJAX

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");
});
});

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).

Javascript - ZeroClipboard copied content doesn't get updated

I have 2 pre blocks, each of them is wrapped with a div and has a copy button.
<div class="code">
<a class="copy">copy</a>
<pre>content of 1st pre</pre>
</div>
<div class="code">
<a class="copy">copy</a>
<pre>content of 2nd pre</pre>
</div>
$('.code').on('mouseenter', function() {
var copy_button = $(this).find('.copy');
var clip = new ZeroClipboard(copy_button, {moviePath: 'ZeroClipboard.swf'});
var content = $(this).find('pre').text();
// at this point, content is always right
// alert(content);
clip.on('mousedown', function(client, args) {
// the content doesn't get updated here
alert(content);
clip.setText(content);
});
});
The problem is, it seems that it always copys the conent of the first-mouseentered-div.
Say I first mouseentered div2, and clicked copy, the content (content of 2nd pre) is copied fine. But then when I try to copy the first pre, the content doesn't get updated, it's still content of 2nd pre.
What am I doing wrong here? How can I fix this?
OK, I found another jQuery plugin - zClip, which is built using the Zero Clipboard library. It's much easier to use and configure.
$('.copy').zclip({
path: 'ZeroClipboard.swf',
copy: function() {
var tocopy = $(this).parent().find('pre').text();
// formatting content
// ...
return tocopy;
},
beforeCopy:function(){
// do something before copy
},
afterCopy:function(){
// do something after copy
}
});
You keep on adding more and more events on mouse enter.
This should unbind events so you don't add each time:
.on('mouseout', function(){
$(this).unbind();
});

Categories

Resources