Can you combine replace_html with a visual_effect in Rails RJS? - javascript

I'm developing a website with Ruby on Rails and I have a div with some content. After clicking a link I want that content to get replaced with some other stuff. This works fine with replace_html and rjs.
However, I'd prefer there to be a slight fade/appear (crossfade?) transition between the old and new content. Also the div will be resized a bit so it'd be cooler if this did a grow/shrink effect. I was thinking Scriptaculous must have something like this built in, but I sure can't find it if they do.
By the way there is a great example of this if you have a Basecamp account: login and click "All people" then "Add a new company" to see the effect in action.
Anyone know how to do this? Thanks!
Brian

To crossfade, you need to position your new content absolutely, and with the same x/y coordinates as the old content. Here's a tested example:
page.insert_html :after, 'old-content', content_tag('p', '[new content]', :id => 'new-content', :style => 'display:none')
page << <<-JS
var oldOffset = $('old-content').cumulativeOffset();
$('new-content').setStyle({
position: 'absolute',
left: oldOffset.left + 'px',
top: oldOffset.top + 'px'
});
JS
page['old-content'].fade :duration => 3
page['new-content'].appear :duration => 3
Note the big block in the middle—some things are easier in Prototype than in RJS.

A strategy could be to put the element in a wrapping div, fade out that wrapping div, replace the HTML in the element, and then fade in the wrapping div again.
I'm not a RJS/scriptaculous user myself, so I'm not sure what the code is, but I'm pretty sure that strategy will work.

Fade out the 1st div.
Blind in the 2nd div at the same time.
As the 1st one fades, the 2nd will appear to expand what's left of the first one.
Well, something like that.
Load up Firebug and step through the code if you want to see what they're calling.

One quick way would be to do the replace and then pulsate the div.

Related

Running jQuery functions one by one to execute CSS transitions

Here is my fiddle. I would like to achieve 'one page full screen' type of webpage. I have two sections; display one at a time by display:block/none;each section contains content; .content1, .content2 respectively; content div works as a button to fire another section. You can also see a fixed header.
Section .intro contains .content1, section .archive contains .content2.
Now, I would like to build following chain of events on click: (i) .content1 fades out, (ii) .intro gets display:none, .archive gains display:block, (iii) .content2fades in.
The other way around, respectively, on click on .content2: (i) .content2 fades out, (ii) .archive gets display:none, .intro gains display:block, (iii) .content1fades in.
I have some experience with CSS, so I made and checked css transitions for fade in, fade out effects. Up to this point, everything is clear for me.
My problem is, however, I do not know how to build the chains of events. I have googled a lot of similar questions and tried some solutions, but had no luck. I have very little experience with JavaScript, so there might be some obvious mistakes in how I tried to implement the solutions.
I do not attach script in my fiddle; I would like to ask if you could point me in the right direction rather than fix my code, because, you see, I am not sure which solution I should show--so far they all look equally hopeless for me.
Should I go with JavaScript? JQuery? Pure CSS? Could you sketch / write some code how you would handle the problem?
Could you review the idea of displayed/hidden sections for the effect I am trying to achieve?
Using jQuery's fadeIn and fadeOut should be fine:
$(".toarchive").click(function(){
$('.intro').fadeOut();
$(".intro").removeClass("active");
$(".intro").css("display", "none");
$(".archive").fadeIn();
$(".archive").css("display", "block");
$(".archive").addClass("active");
});
However, if you're worried about the wait time between fades, you can use setTimeout:
$(".toarchive").click(function(){
$('.intro').fadeOut();
$(".intro").removeClass("active");
$(".intro").css("display", "none");
setTimeout(testThis, 1000);
});
function testThis(){
$(".archive").fadeIn();
$(".archive").css("display", "block");
$(".archive").addClass("active");
}
Try here
Try this, it automaticallys does what you want and it's cleaner.
Just put class show at page container you want to show first then clicking next will loop through pages.
Or you could set page number yourself and it will show that page.
http://jsfiddle.net/ot2gyxme/
var pages = $('.full'),
len = pages.length,
showing = pages.index($('.full.show'));
$('.next').click(function(){
pages.stop().eq(showing).fadeOut(function(){
setTimeout(function(){
showing = ++showing % len; //set this number to show x page
pages.eq(showing).fadeIn();
},1000); //time logo remains visible in ms.
});
});

toggling element with javascript is making the element appear too small until I resize the browser

edit
Since originally posting this question, I've gone down a couple more paths trying to solve the issue. It's still not solved, but now my questions are different. The original question is below, and then I'll add a section below that with updates.
original question
I'm working on a Rails 4 application and having some trouble with JavaScript and the Chartkick gem.
I have two JavaScript functions that make it so that a user can click an icon and an element will drop down below the icon/appear on the page, and the icon will switch from a right-pointing arrow to a down-pointing arrow. The code is this:
function ReverseDisplay(d)
{
if(document.getElementById(d).style.display == "none")
{
document.getElementById(d).style.display = "block";
}
else
{
document.getElementById(d).style.display = "none";
}
}
$(function() {
$('.toggle-icon').click(function() {
$(this).find('i').toggleClass('fa-arrow-circle-o-right fa-arrow-circle-o-down');
});
});
And the haml:
%a{href: "javascript:ReverseDisplay('toggle-stats#{item.id}')", class: 'toggle-icon'}
%i.fa.fa-arrow-circle-o-right
%div{id: "toggle-stats#{item.id}", style: "display: none;"}
= the items to be displayed
It works. However, I expect the items that drop down to take up the full width of the page, like so:
But instead, when I first click the toggle icon, they show up squished, like this:
If I then resize the browser just a tiny bit, the graph pops out to full-width, and it stays that way no matter what I do from there. I can't figure out how to get ahold of the generated mark-up, because this chart comes from Chartkick, as a gem. The generated html in the browser has this line:
<div dir="ltr" style="position: relative; width: 300px; height: 300px;">
Where the width: 300px is what's being changed to width: 1000px when I change the browser size. I don't have to change the browser size permanently or significantly. Once that width has changed to 1000px the first time it stays there - but the minute I refresh the page and click the icon to toggle the chart again, it's back to 300px. I don't know how to hook into this div, because it's generated by the gem and I don't know how to add a class to it. I've tried adding styling to a parent element that ensures all of that parent elements' children are width: 100%, but that doesn't do anything.
Anyway, I don't think that adding a class to it is the solution here. I just have no idea what is - I don't JavaScript incredibly well. I'm pretty much completely new to all front-end work as a whole. What's going on here, and how can I make these charts always be the full width of the page when they're toggled?
Notes: Am testing this in Chrome. I tested in Firefox and it does the same thing.
OK, I'm starting to wonder if this has something to do with the fact that I'm using a JavaScript function in order to capture dynamic item IDs - a page may have any number of these toggle-able charts, and so calling a jQuery function on each id seems impossible, because I don't know what ID is.
I removed the jQuery call, however, and the problem persists.
One of those times when rubber-ducking the Stack Overflow question box has not yet answered my question. So I guess I'll submit and hope for outside help here. :/
adjusted question
This question in the Github issues for Chartkick has lead me down a different path. The solution is not necessarily in attempting to restyle the charts at all. Instead, what I'm trying to do is trigger a resize event, because the chart automatically regenerates when the browser window is resized. This is both what's causing the problem and where the solution seems to lie.
My code:
.row
.col-sm-12
%h3.title-block.second-child
Stats by Video
.panel-groupd#faqList
- #claim.presenter.videos.each_with_index do |video, index|
.panel.panel-default
.panel-heading
%h4.panel-title
%a.chart{data: { toggle: "collapse", parent: "#faqList" }, href: "#video#{index}" }
= "'#{video.title}' at #{video.event.display_name} on #{display_date(video.recorded_at)}"
%div.panel-collapse.collapse{id: "#video#{index}"}
.panel-body
- if video.impressions.count > 0
%h4
Impressions by Hours (24 hours)
= line_chart video.impressions.group_by_day(:created_at, range: 1.day.ago...Time.now).count
...a couple more charts
:javascript
$(".chart").click(function() {
window.dispatchEvent(new Event('resize'));
});
So the intention here is that when I click the .panel-heading, this both drops down the .panel-body with the charts in it and resizes the window, which makes the charts resize correctly (or, rather, should).
It kind of works, in that, when I first click the .panel-heading trigger, it does not resize the charts, but when I click it again, the charts are resized perfectly for a split second... just before they become hidden from view again. :(
I've tried adding a time out to the javascript, like so:
:javascript
$(".chart").click(function() {
setTimeout(1000);
window.dispatchEvent(new Event('resize'));
});
But it doesn't appear to do anything at all.
So what I'm wondering here is how to get this resize event to work once the dropdown .panel-body is out so that the charts will resize appropriately on their own.
Here's a screen cast of the current problem, in case I didn't describe it clearly enough:
https://youtu.be/5quMGABoDs8
I don't know anything about Ruby or Chartkick, but in order to override that inline styling, you would have to use !importantin the css.
So, if you try that technique of giving all the children of the parent element width: 100% again, you might want to implement it something like this:
.importantRule { width: 100% !important; }
$( "parentElement > childElement" ).addClass('importantRule');
(First line goes in your CSS file, second line goes in JS)

Best approach in sliding image and appending some room for content

I'm working with a jquery and I have this image that is the main problem. I googled it but came up with nothing. Here is my content for example.
And when the guy(in the picture above) is being click I want it to slide to the left side and will looked like this. Please see image below.
So what I'm thinking is
1. using addClass and removeClass using jquery or
2. just use jquery .slide or toggle function?
If there's a solution as such how could it be done? Since I only know is using addClass tho. And also what I'm planning is when the image exceeds 800px then the girl(in the image) will be send to back of the guy image.
What you are trying to do is create a mask around the guy. The scope of this question is beyond masking. Most methods of masking don't have large browser support at this moment so posting more on this would be disingenuous. But worth googling otherwise you can use the transform property to move the picture to the left. But you won't get the results you are looking for..
But there is the option of masking the picture in Photoshop and saving it as a PNG. And then utilizing the translate CSS method to move the image to left. This is your best option. But the details of either of these methods are out of scope for this question.
Cut this guy from image and put in another div at needed position. Put blue box between those two images and use slide function. You can cut the guy from his head i think.
Basically you need to have an html structure like this:
<div id='container'>
<div id='couple'></div>
<div id='mask'></div>
</div>
Initially in your css:
#mask {
display: none;
}
And, of course, you have to align horizzontally this two div.
Your jquery will have a behavior like this:
$('#couple').on('click', slide);
var slide = function() {
$target = $('#container');
$mask = $('#mask');
$mask.fadeIn();
$target.animate({
left: "+=50"
}, 500, function() {
/* callback on end*/
});
}
For complete documentation of animate check api jquery.

What do you call a div that slides out from beneath another div when moused over?

I'm trying to create a Javascript effect I'm sure I've seen done many times before. However, I can't seem to find the right terminology for it. It's not a "slider", or a "slide out menu" or a "slide out tab" or a "tab". So far those terms have caused Google to take me to all sorts of examples and tutorials for things that are not what I'm after.
The effect I'm after is like this:
Div 2 sits behind Div 1 until the user mouses over the visible portion of Div 2, which causes it to slide out to reveal more of itself. When the user mouses away, Div 2 slides back underneath Div 1.
What do you call this effect, so that I can find turorials or Javascript code for it? Or if anyone can direct me to an example or explain how to do it, that would be great.
I'm sorry for a terrible code, but do you need something like this?
http://jsfiddle.net/D7Z8v/
$("#smalldiv").hover(function() {
$("#smalldiv").animate({marginLeft: 200});
}, function() {
$("#smalldiv").animate({marginLeft: 0});
});
You probably need to change "marginLeft" inside hover function on something more appropriate, but it's looks like what you needed.
You can use z-index to have div1 above div2 and then you can either use a CSS animation, jQuery animation to change the position of div2 or you can adjust the width of div2.

How to keep div focus when the mouse enters a child node

So I have this page here:
http://www.eminentmedia.com/development/powercity/
As you can see when you mouse over the images the div slides up and down to show more information. Unfortunately I have 2 problems that i can't figure out and I've searched but haven't found quite the right answer through google and was hoping someone could point me in the direction of a tutorial.
The first problem is that when you mouse over an image it changes to color (loads a new image), but there's a short delay when the image is loading for the first time so the user sees white. Do I have to preload the images or something in order to fix that?
My second problem is that when you move your mouse over the 'additional content area' it goes crazy and starts going up and down a bunch of times. I just don't have any idea what would cause this but i hope one of you will!
All my code is directly in the source of that page if you would like to view the source.
Thanks in advance for your help!
Yes, you have to preload the images. Thankfully, this is simple:
var images_to_preload = ['myimage.jpg', 'myimage2.jpg', ...];
$.each(images_to_preload, function(i) {
$('<img/>').attr({src: images_to_preload[i]});
});
The other thing you have to understand is that when you use jQuery you have to truly embrace it or you will end up doing things the wrong way. For example, as soon as you find yourself repeating the same piece of code in different places, you are probably doing something wrong. Right now you have this all over the place:
<div id="service" onmouseover="javascript:mouseEnter(this.id);" onmouseout="javascript:mouseLeave(this.id);">
Get that out of your head. Now. Forever. Always. Inline javascript events are not proper, especially when you have a library like jQuery at your disposal. The proper way to do what you want is this:
$(function() {
$('div.box').hover(function() {
$(this).addClass('active');
$(this).find('div.slideup').slideDown('slow');
}, function() {
$(this).removeClass('active');
$(this).find('div.slideup').slideUp('slow');
});
});
(You have to give all the #industrial, #sustainable, etc elements a class of 'box' for the above to work)
These changes will also fix your sliding problem.
I can see your images (the ones that are changing) are set in the background of a div. Here is a jquery script that preloads every image found in a css file. I have had the same problem in the past and this script solves it. It is also very easy to use:
http://www.filamentgroup.com/lab/update_automatically_preload_images_from_css_with_jquery/
I will take a look at your other problem...
1) You should be using the jquery events to drive your mouseovers. Give each div a class to indicate that its a category container and use the hover function to produce the mouseover/mouseout action you're after.
html
<div id="industrial" class="category"></div>
Javascript
$(".category").hover(
function () {
$(this).find('.container').show();
},
function () {
$(this).find('.container').hide();
}
);
I simplified the code to just do show and hide, you'll need to use your additional code to slide up and slide down.
2) Yes, you need to preload your images. Another option would be "sprite" the images. This would involve combining both the black and white and colour versions of each image into a single image. You then set it as the div's background image and simply use CSS to adjust the background-position offset. Essentially, sliding instantly from the black and white to colour images as you rollover. This technique guarentees that both images are fully loaded.

Categories

Resources