I'm trying to create a slider of posts. I charge the data using ajax and then I apply append to inject the content to a div (id=ajaxinserted1). But I don't want to add this data into screen. I want that data to be added outside of screen (left:100%), so then I can apply a CSS transition to get it on screen with a slide animation effect.
How could I append(data) into the DOM outside the screen?
Thanks
The below code should dynamically calculate the offset based on the width of the images returned from the request. The explanation is in-line. This also required the container to be positioned absolutely.
// Cache the element
var $container = $('.ajaxinserted1');
// Append the images to the container
$container.append(
'<img src="https://www.placehold.it/100">',
'<img src="https://www.placehold.it/100">',
'<img src="https://www.placehold.it/100">',
'<img src="https://www.placehold.it/100">'
)
// Store the offset value
var offsetLeft = 0;
// Loop over the images and update the offset value
$.each($container.children(), function(a, b) {
offsetLeft = offsetLeft - b.width;
})
// Set the offset for the container
$container.css('left', offsetLeft);
// Animation
$('.ajaxinserted1').animate({
left: "10px"
}, 500);
.ajaxinserted1 {
position: absolute;
}
.ajaxinserted1 img {
padding: 10px;
height: 100px;
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ajaxinserted1"></div>
If I understand your question correctly, you just want to append your post under the existing ones and style it so it appears off screen so it can then slide in. So maybe something like...
1) Append your new post HTML into the content div with a class on it called 'new-post'
2) With CSS for new-post class...
.new-post {
position:relative;
left:100%;
}
3) Do your CSS transition to slide it back on screen and remove the class once finished.
Notes:
You may need to set the left attribute in absolute pixels, e.g. 600px, it depends on the layout of your page and where you want it to slide in from.
You could consider using opacity:0 and doing a fade in transition as well
Related
I am creating an ajax slider with only the one "slide" thats data reloads during slide.
My current method is to animate the absolute positioned element out of parent viewport, jump to right hand side of viewport and slide back in. This gives the illusion of the element sliding.
I have an idea of cloning the slide and appending it to the right hand side of the original element, animating left so clone is in view and the removing the original element.
I have got as far as creating the clone and removing original but am unsure of how to append the clone to the right hand side of original element. Any thoughts on how to do this would be appreciated.
HTML STRUCTURE
<!-- Relative Parent -->
<div id="gameBoxWrap">
<!-- The Slide -->
<div class="gameBox">
<div class="gameBoxContent">
<!-- Have removed content for readability -->
</div>
</div>
</div>
CSS
#gameBoxWrap {
position: relative;
overflow: hidden;
width: 100%;
height: 700px;
}
.gameBox {
position: absolute;
top: 2px;
left: 1px;
width: 938px;
height: 690px;
padding: 20px;
}
JS
//
// CREATES A CLONE OF ELEMENT - I am trying to append the clone to the right hand side of the original element
var $el = $('.gameBox');
$el.clone(true).appendTo('#gameBoxWrap');
// The current settings below are as follows:
//
// 1. Slide Element out of relative parent viewport
// 2. Jump Element to right hand edge of parent viewport
// 3. Slide Element to orignal position
//
//
// My thought pattern for ideal process
//
// 1. Wait for clone to be appended on right hand side
// 2. Slide left so Original Element is out of viewport
// 3. Remove Orginal Element
var settings =
[
[ {"left": "-950px"},{duration: 400,complete: function() {$(this).css("left", window.innerWidth + $(this).width());}} ],
[ {"left": "1px"}, {duration: 400} ]
];
$(".gameBox").queue("_fx", $.map(settings, function(options, i) {
return function(next) {
return $(this).animate.apply($(this), options).promise().then(next);
};
})).dequeue("_fx");
// REMOVES ORIGINAL ELEMENT
$el.remove();
Replace your javascript section with the following code. Here's the breakdown
Get the box, assign it to a variable for future use.
Clone it, assign that to a variable for future use.
Append the the clone hidden
Set the left value to be off canvas
Set the animation of the clone
Show the clone
Set the animation of the original
Set the left value of the original to be off canvas
After the animation has finished, remove the original
var el = $('.gameBox');
var elNew = el.clone(true);
$('#gameBoxWrap').append(elNew.hide());
elNew.css('left', '100%');
elNew.show();
el.css('transition', 'left 1s ease-in-out');
el.css('left','-100%');
elNew.css('transition', 'left 1s ease-in-out');
elNew.css('left','0px');
window.setTimeout(function(){
el.remove();
},1000);
The trouble is that I need these images with generated IDs "cam_snap_XXX" to become a different width if they are dragged and dropped into this area. I can make the height change but NOT THE WIDTH because the width is designated to 20px if x==1. Never is the image height specified therefore I believe that is the reason it is changeable? Q: How can I make these image widths change from 20px to 100px if "dragged"?
while (cnt <= 100) {
cam_icon=document.getElementById('cam_snap_' + cnt);
cam_icon.style.visibility = 'hidden';
if (x==1) {
cam_icon.style.width = '20px';
cam_icon.style.visibility = 'visible';
}
cnt++;
}
The height changes from the following javascript...
//js for adding class "dragged" which gives new height and width image parameters
$('.droparea td.drop').droppable({
onDrag: function (e, source) {
$(this).addClass('dragged'); //Changes height correctly not width though.
}
}
And the css..
//css for attempting to change image width and height on drop
.dragged{
height: 100px; //Works because height stretches image height from ~20px to 100px.
width: 100px; //**Doesn't work and is useless because width remains 20px.**
}
Should I try removing the class before adding class 'dragged' to these images? Using removeClass()? Any ideas are welcome even if not the solution.
This part of javascript modifies your HTML
cam_icon.style.width = '20px';
cam_icon.style.visibility = 'visible';
to
<someTag id="cam_snap_x" style="width:20px;visibility:visible">
According to css rules inline style (inside an HTML element) has the highest priority. so you'll have to change attribute value to see changes in UI.
Solution 1: change your onDrag function like below.
$('.droparea td.drop').droppable({
onDrag: function (e, source) {
$(this).width(100).height(100); //This will change the style property
}
}
Solution 2: Use !important to prioritize value specified in class over inline style attribute
.dragged{
height: 100px;
width: 100px !important;
}
I have a 100% height div with a nav underneath it and more content under that.
When the user scrolls passed the nav it sticks to the top of the page and when the user goes back to the 100% height div the nav is left behind.
As the div is 100% height the 'data-offset-top' for the nav needs to change dynamically.
The following code works for that:
$('#navigation').affix({
offset: {
top: $('#hero').height()
}
});
However when I resize the page the value of the offset does not get readded to the offset.
The following code checks for the page height to change and then gives the new height to the data-offset-top but it does not ` function affixChange()
{
$('#navigation').attr('data-offset-top', $('#hero').height());
$('#navigation').affix({
offset: {
top: $('#hero').height()
}
});
}
affixChange();
setInterval(function(){
affixChange();
console.log($('#hero').height());
}, 1000)
Why is my method not working?
Is there a better way to do this?
Bootstrap gives you the possibility to pass a function to calculate the offset dynamically:
$('#navigation').affix({
offset: {
top: function() { return $('#hero').height(); }
}
});
Unfortunately if you need data-offset-top to be set dynamically you need to handle this manually. While domachine provides the correct answer I wanted to offer here a way to re-calculate the value on page resize and also to add a space holder so that affixing runs smooth e.g. no page jumping when the contents gets affixed. This was an issue for me.
It re-calculates data-offset-top dynamically
It sets the offset space dynamically. The space will replace affix when affixed
So I use the following HTML:
<div class="my-affix" data-spy="affix" data-offset-top-dynamic="true" data-content-space-holder="#my-affix-space-holder"></div>
<div id="my-affix-space-holder"></div>
The following CSS:
.my-affix + #my-affix-space-holder {
display: none;
}
.my-affix.affix + #my-affix-space-holder {
display: block;
}
And a JS script:
var $dynamicAffixes = $('[data-offset-top-dynamic]');
$dynamicAffixes.each(function(){
// data-target is used for the element that should be affixed while data-spy is used to have some scroll breakpoint
var $thisAffix = $(this);
var $thisAffixMarginPlaceholder = $($thisAffix.attr('data-content-space-holder'));
var currentAffixHeight = $thisAffix.outerHeight();
// Assign the affix height to content placeholder - to add a margin in the page because of missing content
$thisAffixMarginPlaceholder.css('height', currentAffixHeight);
// Initialize affix height where it should trigger to become sticky
$thisAffix.affix({
offset: {
top: Math.round($(this).offset().top)
}
});
$(window).on('resize', function(){
var isAlreadyAffixed = false;
// Restore affix to its original position if scrolled already so we can calculate properly
if ($thisAffix.hasClass('affix')) {
$thisAffix.removeClass('affix');
isAlreadyAffixed = true;
}
var currentAffixPosition = Math.round($thisAffix.offset().top);
var currentAffixHeight = $thisAffix.outerHeight();
$thisAffix.data('bs.affix').options.offset.top = currentAffixPosition; // a hack
$thisAffixMarginPlaceholder.css('height', currentAffixHeight);
if (isAlreadyAffixed) {
$thisAffix.addClass('affix');
$thisAffix.affix('checkPosition');
}
});
});
Have you tried monitoring the window for a resize event?
$(window).resize(function() {
affixChange();
});
Let's say I have an image, cat.jpg, and when clicked I want to clone it.
$('img.cat').on("click", function() {
$(this).clone().appendTo('#container');
});
Upon duplication, however, I want the new cat.jpg to appear as half the size of the original. And I want this to continue happening each time a new cat.jpg is clicked.
Any ideas on how to go about accomplishing this? Is it even possible to inject new styling/classes/parameters via .clone()?
It sounds like the following is what you're after:
// If all images are within #container, use $("#container") instead:
$(document).on("click", "img.cat", function () {
var original = $(this);
original.clone().css({
width: original.width() / 2,
height: original.height() / 2
}).appendTo("#container");
});
Fiddle: http://jsfiddle.net/G6XTz/
Of course, you may have wanted the newly added image to be half the size of the last cat image, rather than the cat image clicked:
Fiddle2: http://jsfiddle.net/G6XTz/1/
Caveat:
The width and height can only divide so far; eventually you'll run into some problems. Better check the result of division first, and make a decision to do something else when it makes sense.
Just setting the width to half seems to be enough with an img element, the height gets set automatically in proportion to the width:
$('#container').on('click','img.cat', function() {
$(this).clone()
.appendTo('#container')
.width(function(i,v) { return v/2;});
});
Demo: http://jsfiddle.net/Mr2x8/
But if you find you need to set the width and the height here's one way to do it:
$('#container').on('click','img.cat', function() {
var $this = $(this);
$this.clone()
.appendTo('#container')
.width($this.width()/2)
.height($this.height()/2);
});
Demo: http://jsfiddle.net/Mr2x8/1/
id do this:
$(this).clone().addClass('small').appendTo('#container');
this adds the css class small to the clone of this.
Create a new class with the specific new styling you want to get changed dynamicaly in your CSS file.
.newClass {
//example green outline
outline: solid thin green;
}
And then modify your script:
$('img.cat').on("click", function() {
$(this).clone().addClass('newClass').appendTo('#container');
});
EDIT :
If the only thing you want to change is the size of the img for lets say 10% each click then:
$('img.cat').on("click", function() {
var width = $(this).width() * 0.9;
var height = $(this).height() * 0.9;
$(this).clone().css({"width":width+"px", "height":height+"px"}).appendTo('#container');
});
The above code will produce the same image but 10% smaller than the image clicked .
If you want to click only the initial image then simply put the width and height variable outside the click function and update them inside for each click.
NOTE :
In the css() you add +"px" if initial width is in px else you add +"%" if it is in percentage.
My goal is to dynamically generate background images for divs.
I've got a function that:
Draws an image on canvas;
Gets data URL of the image;
Creates a bgDiv with the image as background;
Prepends the bgDiv to a given div element.
Here's the code of the 3rd and 4th points:
var bgDiv = document.createElement('div');
$(bgDiv).css({
position: 'absolute',
left: '0px',
top: '0px',
width: '100%',
height: '100%',
background: 'url(' + url + ')',
});
$(div).prepend(bgDiv);
The problem is: the bgDiv is drawn in front of children of div. I've figured out this is because of the position: absolute property, which is set on bgDiv while regular children in my case have no position set.
How can I get the bgDiv element to be drawn on the bottom of all children no matter what they are?
Disclaimer: I know that I could just set background-image property of div, but it's not sufficient for my purposes.
I'm testing this in recent Firefox, and I need quite universal solution.
Edit: if you're actually using $(div) as your selector, that's one problem. Use the content <div>'s ID or class instead.
Edit 2: If you're doing this multiple times (with different background images) I'd make bgDiv a class instead, then dynamically assign their positions. It will save you some JS.
bgDiv has to be "below" the rest of the div content, so give it a lower z-index than that of the content; this could cause it to fall underneath another element, however. In this case, set the content of the div to a higher z-index (and leave bgDiv's z-index to the default auto).
.bgDiv {
position: 'absolute';
z-index:-1;
/* left: '0px'; Set in JS */
/* top: '0px'; Set in JS */
width: '100%';
height: '100%';
/* background: 'url(' + url + ')'; Set in JS */
}
You defined your problem correctly in your question, you need to have bgDiv draw in a position lower than the children of div. In other words you need to set the z-index of all children to be higher, if you need to do this programatically then do
var bgDiv = $('<div class="bgDiv">').css('background', 'url(' + url + ')');
$(div).children().css({zIndex,2});
$(div).prepend(bgDiv);
With a defined class bgDiv in your CSS as #trojansdestroy suggested
.bgDiv {
position: absolute;
z-index:-1;
left: 0;
top: 0;
width: '100%';
height: '100%';
}