After I clicked on link, which navigate to another page I have to scroll the first (the earliest) alarm occurrence (which is marked as a red text) at the top of "tbody" div. Each row have id='tab_content' and a table data class = 'td_list_row_center'. When alarm occurs, tds are changing color from black to red and a name class = 'td_list_row_center font-red".
I've tried to handle red occurrence and if it was found, scroll at the top inside "tbody" div. The second row should be with black font (non-alarm)
<script>
function scrollToFirstRedAlarmOccurence(red_occurrence) {
$('tbody').animate({
scrollTop: red_occurrence.offset().top
}, 2000);
}
var red_occurrence = document.getElementsByClassName("td_list_row_center font-red");
if(red_occurrence)
scrollToFirstRedAlarmOccurence(red_occurrence);
else
null
</script>
After clicking on the link and table shows, nothing happens (like script doesn't work). I expect it to scroll to the first red occurrence from a huge dataset. After I scroll the table up I would see another later red occurrencies. Below actual and expected results as pics:
[Actual res.] -> https://ibb.co/1zn4ty9
[Expected res.] -> https://ibb.co/Jy6FrL6
Parameters for 'getElementsByClassName' are incorrect. Use them as following.
<script>
function scrollToFirstRedAlarmOccurence(red_occurrence) {
// make jQuery object for first element
$('tbody').animate({
scrollTop: $(red_occurrence[0]).offset().top,
}, 2000);
}
setTimeout(() => {
// select "font-red" classed elements
var red_occurrence = document.getElementsByClassName("font-red"); // you can use jQuery selector too
if(red_occurrence.length) { // check for array length
scrollToFirstRedAlarmOccurence(red_occurrence);
}
}, 1000); // wait for DOM to render
</script>
Basically, you can debug your code to check if they are getting correct values. I have made some correction which would work for your case.
Related
My goal:
To enable a user to load a template (which contains preset jquery, html and css) to allow them to click one of five dots to trigger an animation on an image.
My issue:
When I load more than one of these templates to my page, my animation value (margin-left in this case) applies double the number of times that there is an instance of this template on the page. If my template is loaded twice, the margin-left sets to a value, jumps to the correct value, then back before finally setting on the correct value. This means that if I was to add 10 instances to the page, it would take 20 times as long to get that last value.
Before testing I thought that my code would be ok, as due to the context and .once()function, I believed it would only fire once.
All html and CSS are functioning as expected, it's just the jQuery is an issue.
My code:
(function ($) {
Drupal.behaviors.click_the_dots = {
attach: function (context, settings) {
$('.wrapper_class', context).once('click_the_dots', function () {
// Prevent other buttons from being clickable until the
// previous animation is complete.
var animationDone = false;
function clickDots(dotNum) {
$('.dot_class_num_' + dotNum).click(function () {
// Setup context, to keep animations to the container in which the dots exist.
var findElem = $(this).parent().parent().parent().find('.inner_wrapper');
// Prevent other buttons from being clickable until the
// previous animation is complete.
if (animationDone === false) {
animationDone = true;
// Find the visible image.
var animatingImage = findElem.find('.dot_class_num_active');
// Find the image that will be animating in.
var thisImageAnim = findElem.find('.dot_num_img_src_' + dotNum);
if (animatingImage.is(thisImageAnim)) {
// Can't click on the same dot again, until another dot is clicked.
animationDone = false;
return;
} else {
// Animate out the already visible image.
// Remove the visible image class as it's going to be hidden.
findElem.find('.dot_class_num_active').removeClass('dot_class_num_active');
// Animate it to hide to the left.
animatingImage.animate({
marginLeft: '-10%',
opacity: 0
}, 280, 'easeInOutQuad');
// Animate in the image associated with the dot click
// Set the image css to be further right in order to animate to left at 0.
thisImageAnim.css('margin-left', '10%').delay(200).animate({
marginLeft: '0',
opacity: 1
}, 300, 'easeInOutQuad', function () {
// Set the now visible image to the visible image.
thisImageAnim.addClass('dot_class_num_active');
}).promise().done(function () {
// Now allow the other dots to be clicked.
animationDone = false;
});
}
}
});
}
// For each of the five dots.
for (i = 1; i <= 5; i++) {
clickDots(i);
}
});}};})(jQuery);
I would like to add as many instances of this jQuery as required, but only have the function be looped through once. I'm not sure how to check if this has already been done, or how to ensure that once it has been done at least once, it shouldn't happen again.
:)
I figured out what my issue was - I was attaching the behaviour to the wrapper class of my content, i.e. $('.wrapper_class', context).once... - this meant that it attached the behaviour to each instance of this class, of which there could be many.
What I did was attach the behaviour to a higher parent element, of which I knew there would be only one instance. It attaches just once and the code works perfectly.
Thanks to the commenters above who helped me realise my issue!
I've got a container that includes several icons the user can hover over and be shown a block of text next to it. I'm grabbing the blocks of text from an array and have a randomize function so that they're always shown a different block of text when revisiting the page.
I ran into an issue where every time you hover over an icon, it keeps adding more array elements, because the function gets called each time you hover over the icon. So I decided to use the one() method so the function only runs once, however that's where my real issue is. Using the one() method doesn't show ANY text, and I'm pretty sure it's due to the nested function I have.
You can test this out here: http://www.evanvolmering.com/bootstrap/docs/examples/carousel/eyeswideshut.html
In the banner a video will play, and shortly into it a little icon will appear in the bottom of left of the banner. Hovering over it will show some text. When you hover over it again it adds another array item, and so on. It works, but I don't want it to keep adding array items.
10 seconds later another icon will appear to the top right, which currently has the one() method applied to it. As you can see nothing happens when you hover over it. Not sure where to go from here.
My randomize code (which I got from another StackOverflow answer):
var numRandoms = 14;
function makeUniqueRandom() {
if (!uniqueRandoms.length) {
for (var i = 0; i < numRandoms; i++) {
uniqueRandoms.push(i);
}
}
var index = Math.floor(Math.random() * uniqueRandoms.length);
var val = uniqueRandoms[index];
uniqueRandoms.splice(index, 1);
return val;
}
My code which currently 'works' but keeps adding more array items on hover:
$('img.button1').hover(function(){
$('p.trivia1').fadeIn("slow");
$( 'p.trivia1' ).append(makeUniqueRandom());
},
function(){
$("p.trivia1").stop().fadeOut("slow");
});
My code that uses one() but doesn't do anything on hover:
$('img.button2').one("hover",function(){
$('p.trivia2').fadeIn("slow");
$( 'p.trivia2' ).append(makeUniqueRandom());
},
function(){
$("p.trivia2").stop().fadeOut("slow");
});
Use mouseenter/mouseleave instead of hover
$('img.button1').on('mouseenter',function(){
$('p.trivia1').fadeIn("slow");
$( 'p.trivia1' ).append(makeUniqueRandom());
}).on('mouseleave',function(){
$("p.trivia1").stop().fadeOut("slow");
});
I'm working with cookies to run or not run a jQuery animation someone else built:
$(function () {
$('div.transitional').click(function () {
$('div.intro').removeClass('hidden');
$('div.final').off('click');
});
ShowDiv($("div.transitional.hidden")[0]);
});
function ShowDiv(target) {
target = $(target);
target.removeClass('hidden');
target.delay(500).animate({
opacity: 1.0
}, 300, 'easeInExpo', function () {
ShowDiv($("div.transitional.hidden")[0]);
})
}
I have the cookie part working, but I'm confused about the anonymous function and the "ShowDiv" function.
What is each part doing?
Functionally, the animation makes visible a series of pictures, then the whole site. I want to skip the animation and just make the whole site visible (if cookies='visited'.) I'd like to do this without rewriting the animation script.
Here's a link: http://claytonsalem.com/bottlecap.
What happens now is if you have the cookie the animation doesn't run and everything is hidden.
That script only fades in elements, one after the other. If you want to skip that, use something like this in the anonymous function (which is also known as a DOM ready handler) :
$(function() {
$('div.transitional').click(function() {
$('div.intro').removeClass('hidden');
$('div.final').off('click');
});
if(cookies === "visited") //Assuming you already have the variable set.
ShowDiv($("div.transitional.hidden")[0]);
else
$("div.transitional.hidden").css('opacity', 1).removeClass('hidden')
});
I will focus on how it works:
$("div.transitional.hidden")
This would select ALL elements with div.transitional.hidden, placing them in a list.
By placing [0] in the selector, we are picking ONLY the first element in this list.
Then, when the script begins to run, this element is modified by target.removeClass('hidden'), which removes the hidden class.
When the scripts ends, it calls the $("div.transitional.hidden")[0] selector again, but this time it will not include the previously selected element (because it no longer has the hidden class).
That's why the script show images one after the other: it removes the hidden class and selects the next remaining element.
You might refer to Karl's answer on how to show your whole site.
I have a HTML page with a frame having lot of lines and a button "Next". On clicking Next Button, I should be able to navigate to a paragraph having orange color. All the paragraphs having orange color will be of same class.
That means, on page load I should be able to navigate to 3rd paragraph. On another click I should go to 6th paragraph and so on..
I tried to use document.getelementsbyclassname(). But I was not able to write logic to navigate to that particular location. Please help me out.
You can do this , like this
Working DEMO
$("p:first").addClass("active");
$(document).on("click","#ip",function(){
if($("p.orange:last").hasClass("active")){
var topVal = $("p:first").offset().top;
$("html body").animate({
scrollTop:topVal
},500,function(){
$("p").removeClass("active");
$("p:first").addClass("active");
});
}
else{
var nextElem = $("p.active").nextAll("p.orange:first");
var topVal = nextElem.offset().top;
//alert(topVal);
$("html body").animate({
scrollTop:topVal
},500,function(){
$("p").removeClass("active");
nextElem.addClass("active");
});
}
});
You can try this. First, create a variable called, lets's say, number which stores which paragraph we currently need to scroll to. Like 1st, 2nd, etc. When the page loads, it's value will be 1.
var number=1;
The next step is to add ids to all the orange paragraph. The first paragraph gets id orange1, the second one gets id orange2 and so on. You can either do this manually or if there are too many paragraphs you can try adding it by looping or something like that.
Now assuming the Next button has an id called 'button' you can add this code:
$('#button').click(function() {
$('html, body').animate({
scrollTop: $('#orange'+number).offset().top
}, 1000);
number++;
});
Now, whenever you click on the Next button, the page should scroll to the correct paragraph. Hope this helps.
I need to hide a div and, with this code it works fine:
var idObj = $(this).attr('key');
var valH = $(this).attr('hideval');
var valS = $(this).attr('showval');
if ($('div[name='+idObj+']').attr('isdisplay') == 'no') {
$('div[name='+idObj+']').children().show("slow");
$('div[name='+idObj+']').attr('isdisplay','yes');
var divTitle = $('div[name='+idObj+']').children().first();
var divArrow = $(this).children().first();
//.attr('src',prefixImg+valH);
//divTitle.show();
//divArrow.show();
$(this).children().first().attr('src',prefixImg+valH);
} else {
var divTitle = $('div[name='+idObj+']').children().first();
var divArrow = $('div[name='+idObj+']').children().last();
//.attr('src',prefixImg+valS);
$('div[name='+idObj+']').children().hide();
$('div[name='+idObj+']').attr('isdisplay','no');
divTitle.show();
divArrow.show();
$(this).children().first().attr('src',prefixImg+valS);
}
My div is hidden and the Title and arrows to reopen the div are shown. But if I try to use hide("slow") the divTitle and divArrow don't appear when my div is closed. Same problem using hide(1000).
Is there a difference between hide with and without "slow" parameter?
thanks,
Andrea
From the official site
The matched elements will be hidden immediately, with no animation. This is roughly equivalent to calling .css('display', 'none'), except that the value of the display property is saved in jQuery's data cache so that display can later be restored to its initial value. If an element has a display value of inline, then is hidden and shown, it will once again be displayed inline.
When a duration is provided, .hide() becomes an animation method. The .hide() method animates the width, height, and opacity of the matched elements simultaneously. When these properties reach 0, the display style property is set to none to ensure that the element no longer affects the layout of the page.
So, if hide is used without delay, it hides immediately without animating - eg, poof.
If it's used with time, it becomes animated, so it disapears over time.
For your problems, it is difficult to judge without the corresponding html code.
$(element).hide() hides an element instantly, where $(element).hide('slow') will animate its disappearance (slowly).
It looks like (though I'm not sure) you want to do stuff after the animation is finished. In that case, do something like this:
var that = this; // here to preserve scope for the block below
$('div[name='+idObj+']').children().hide('slow', function() {
// This stuff happens after the hide animation is done.
$('div[name='+idObj+']').attr('isdisplay','no');
divTitle.show();
divArrow.show();
$(that).children().first().attr('src',prefixImg+valS); // <= note "that" instead of "this"
});
According to the jQuery documentation
The strings 'fast' and 'slow' can be supplied to indicate durations of
200 and 600 milliseconds, respectively.
Also duration in milliseconds can be supplied to it..