I'm trying to remove a span with class, using jquery. My goal is to remove this span, when screen smaller then 480px. I already tried with .remove(); but it does not remove the span, when screen is lower then 480px.
I am using CSS / media queries to control and customize the page.
This is my Fiddle: FIDDLE EXAMPLE
HTML
<span class="textbox">This is what we made of you!</span>
CSS
#media screen and (max-width: 368px) {
.container{width: 368px; margin: 0 auto;
padding: 0; display: block;}
span .textbox{display: none;}
.nav{display: none;}
.header{width: 368px;}
}
JQUERY
$(document).ready(function () {
var words = [
'Special', 'Dynamic', 'Simple', 'Great', 'Better',
'Stronger', 'Stylish', 'Flawless', 'Envied',
'Strong', 'Sucessful', 'Grow', 'Innovate', 'Global',
'Knowledgable', 'Unique', 'Trusted', 'Efficient',
'Reliable', 'Stable', 'Secure', 'Sofisticated',
'Evolving', 'Colorful', 'Admirable', 'Sexy', 'Trending',
'Shine', 'Noted', 'Famous', 'Inspiring', 'Important',
'Bigger', 'Stylish', 'Expand', 'Proud', 'Awesome',
'Solid'
], i = 0;
var getRandomWord = function () {
return words[Math.floor(Math.random() * words.length)];
};
setInterval(function(){
$('.textbox').fadeOut(500, function(){
$(this).html(getRandomWord()).fadeIn(500);
});
}, 5000);
});
span .textbox{display: none;}
should be:
span.textbox{display: none;}
because your original code would select all elements with a textbox class which have a span parent, and not the actual span element with the textbox class.
UPDATE
I didn't catch you're using fadeIn that will actually override your display: none property. The quickest fix (without having to check the window width in JS and all that...) is to animate the opacity instead of using fades because that won't change the display state of the element and your CSS rule will remain active.
So, your interval function should be:
setInterval(function(){
$('.textbox').animate({'opacity': 0}, 500, function(){
$(this).html(getRandomWord()).animate({'opacity': 1}, 500);
});
}, 3000);
See it in action here: http://jsfiddle.net/9B7vz/3/
Your current CSS does actually hide the text when the width is reduced to below 480px, but the jQuery fadeIn function brings it back into view, as fadeIn will change the display property of that element.
Try
#media screen and (max-width: 480px) {
.textbox {
display: none;
}
}
then
var interval;
function handler() {
var width = $(window).width();
//if window size is > 480 and there is no interval set then create a new interval
if (width >= 480 && !interval) {
interval = setInterval(function () {
$('.textbox').fadeOut(500, function () {
$(this).html(getRandomWord()).fadeIn(500);
});
}, 5000);
} else if (width < 480 && interval) {
//if window width < 480 and there is a interval clear it and hide the textbox
clearInterval(interval);
interval = undefined;
$('.textbox').hide();
}
}
handler();
//to handle resizing of window
$(window).resize(handler);
Demo: Fiddle
Related
I'm looking for a performant and also smooth solution for links that scroll their text inside of their inline-block box like a marquee effect.
$(document).ready(function() {
function scroll(ele){
var s = $(ele).text().substr(1)+$(ele).text().substr(0,1);
$(ele).text(s);
}
scrollInterval = null;
function startScrolling(e) {
if (!scrollInterval) {
scrollInterval = setInterval(function(){
scroll(e)
},100);
}
}
function stopScrolling(e) {
clearInterval(scrollInterval);
scrollInterval = null;
}
$(".mali").hover(function(){
startScrolling($(this));
});
$(".mali").mouseout(function(){
stopScrolling($(this));
});
$(".mali").mousedown(function(){
stopScrolling($(this));
});
});
.mali {
display: inline-block;
background: black;
color: white;
padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Something something darkside, Something something complete.
My solution so far is something I actually found here on stackoverlow in another thread and tried to work with it.
Two problems though.
1.) As this is basically using an interval to loop through the single letters this effect is not very smooth. The effect is stuttering.
Has anyone an Idea on how to make this more smooth? Maybe in that case don't use this method at all and maybe use a CSS transition to animate the text?
2.) Does anyone have a clever solution on how to return to the initial state once I hover off? I want the effect on hover but when moving the mouse off the link it should animate back to the initial text state.
Thanks,
Matt
2) You can save initial state and then just revert it:
$(document).ready(function() {
function scroll(ele){
var s = $(ele).text().substr(1)+$(ele).text().substr(0,1);
$(ele).text(s);
}
scrollInterval = null;
function startScrolling(e) {
if (!scrollInterval) {
$(e).data("text", $(e).text());
scrollInterval = setInterval(function(){
scroll(e)
},100);
}
}
function stopScrolling(e) {
clearInterval(scrollInterval);
scrollInterval = null;
$(e).text($(e).data("text"));
}
$(".mali").hover(function(){
startScrolling($(this));
});
$(".mali").mouseout(function(){
stopScrolling($(this));
});
$(".mali").mousedown(function(){
stopScrolling($(this));
});
});
.mali {
display: inline-block;
background: black;
color: white;
padding: 10px;
transition: all .2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Something something darkside, Something something complete.
1) As a smooth animation, i thought of this as a PoC. Maybe it will help you with further ideas.
$(document).ready(function() {
// Those global data could be stored in element's data.
var indent = 0,
width = 0,
padding = 10;
function scroll(ele){
// Every iteration decrease indent by value
indent -= 1;
// If is indent greater than or equal than real width
// (width with padding) reset indent.
if(-indent >= width+padding)
indent = 0;
// Aplly property
$(ele).css("text-indent", indent);
}
var scrollInterval = null;
function startScrolling(e) {
if (!scrollInterval) {
// Get text and real width
let text = $(e).text();
width = $(e).width()
$(e)
// Set real width & height, so that container stays
.width($(e).width())
.height($(e).height())
// Save text to data for reset
.data("text", text)
// Add 2 spans with text:
// <span>text</span><span>text</span>
// Where second span has defined padding on the left
.html($("<span>").text(text))
.append($("<span>").text(text).css("padding-left", padding+"px"));
resumeScrolling(e);
}
}
function stopScrolling(e) {
pauseScrolling(e);
// Reset
$(e)
// Revert real text and reset indent
.text($(e).data("text"))
.css("text-indent", indent = 0);
}
function pauseScrolling(e) {
clearInterval(scrollInterval);
scrollInterval = null;
}
function resumeScrolling(e) {
if (!scrollInterval) {
// Every 30ms repeat animation. It must be at least 25x per second
// so it runs smoothly. (So 1 - 40).
scrollInterval = setInterval(function(){
scroll(e)
},30);
}
}
$(".mali").hover(function(){
startScrolling($(this));
});
$(".mali").mouseout(function(){
stopScrolling($(this));
});
$(".mali").mousedown(function(){
stopScrolling($(this));
});
$("#start").click(function(){
startScrolling($(".mali"));
});
$("#stop").click(function(){
stopScrolling($(".mali"));
});
$("#pause").click(function(){
pauseScrolling($(".mali"));
});
$("#resume").click(function(){
resumeScrolling($(".mali"));
});
});
.mali {
display: inline-block;
background: black;
color: white;
padding: 10px;
/*
This could help, but you can't reset text-indent without animation.
transition: all .1s;
*/
overflow: hidden;
vertical-align: middle;
}
/* When you hover element, new span elements
can't take pointer events, so your elements
stays hovered. */
.mali span {
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Something something darkside, Something something complete.
<br><br>
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="pause">Pause</button>
<button id="resume">Resume</button>
Idea behind this is:
make element overflow:hidden; so no text will overflow
set fix dimension
duplicate text inside
change text indent every x miliseconds (x < 40 so it is smooth, must be at least 25fps)
when it overflows, reset it so it can be in infinite loop
I'm using a WordPress plugin (open source) that will allow you to add an expandable widget for a WooCommerce product category.
This is the JS:
// mtree.js
// Requires jquery.js and velocity.js (optional but recommended).
// Copy the below function, add to your JS, and simply add a list <ul class=mtree> ... </ul>
;(function ($, window, document, undefined) {
// Only apply if mtree list exists
if($('ul.mtree').length) {
// Settings
var collapsed = true; // Start with collapsed menu (only level 1 items visible)
var close_same_level = true; // Close elements on same level when opening new node.
var duration = mtree_options.duration; // Animation duration should be tweaked according to easing.
var listAnim = true; // Animate separate list items on open/close element (velocity.js only).
var easing = mtree_options.easing_type; // Velocity.js only, defaults to 'swing' with jquery animation.
// Set initial styles
$('.mtree ul').css({'overflow':'hidden', 'height': (collapsed) ? 0 : 'auto', 'display': (collapsed) ? 'none' : 'block' });
// Get node elements, and add classes for styling
var node = $('.mtree li:has(ul)');
node.each(function(index, val) {
$(this).children(':first-child').css('cursor', 'pointer')
$(this).addClass('mtree-node mtree-' + ((collapsed) ? 'closed' : 'open'));
$(this).children('ul').addClass('mtree-level-' + ($(this).parentsUntil($('ul.mtree'), 'ul').length + 1));
});
// Set mtree-active class on list items for last opened element
$('.mtree li > *:first-child').on('click.mtree-active', function(e){
if($(this).parent().hasClass('mtree-closed')) {
$('.mtree-active').not($(this).parent()).removeClass('mtree-active');
$(this).parent().addClass('mtree-active');
} else if($(this).parent().hasClass('mtree-open')){
$(this).parent().removeClass('mtree-active');
} else {
$('.mtree-active').not($(this).parent()).removeClass('mtree-active');
$(this).parent().toggleClass('mtree-active');
}
});
// Set node click elements, preferably <a> but node links can be <span> also
node.children(':first-child').on('click.mtree', function(e){
// element vars
var el = $(this).parent().children('ul').first();
var isOpen = $(this).parent().hasClass('mtree-open');
// close other elements on same level if opening
if((close_same_level || $('.csl').hasClass('active')) && !isOpen) {
var close_items = $(this).closest('ul').children('.mtree-open').not($(this).parent()).children('ul');
// Velocity.js
if($.Velocity) {
close_items.velocity({
height: 0
}, {
duration: duration,
easing: easing,
display: 'none',
delay: 100,
complete: function(){
setNodeClass($(this).parent(), true)
}
});
// jQuery fallback
} else {
close_items.delay(100).slideToggle(duration, function(){
setNodeClass($(this).parent(), true);
});
}
}
// force auto height of element so actual height can be extracted
el.css({'height': 'auto'});
// listAnim: animate child elements when opening
if(!isOpen && $.Velocity && listAnim) el.find(' > li, li.mtree-open > ul > li').css({'opacity':0}).velocity('stop').velocity('list');
// Velocity.js animate element
if($.Velocity) {
el.velocity('stop').velocity({
//translateZ: 0, // optional hardware-acceleration is automatic on mobile
height: isOpen ? [0, el.outerHeight()] : [el.outerHeight(), 0]
},{
queue: false,
duration: duration,
easing: easing,
display: isOpen ? 'none' : 'block',
begin: setNodeClass($(this).parent(), isOpen),
complete: function(){
if(!isOpen) $(this).css('height', 'auto');
}
});
// jQuery fallback animate element
} else {
setNodeClass($(this).parent(), isOpen);
el.slideToggle(duration);
}
// We can't have nodes as links unfortunately
e.preventDefault();
});
// Function for updating node class
function setNodeClass(el, isOpen) {
if(isOpen) {
el.removeClass('mtree-open').addClass('mtree-closed');
} else {
el.removeClass('mtree-closed').addClass('mtree-open');
}
}
// List animation sequence
if($.Velocity && listAnim) {
$.Velocity.Sequences.list = function (element, options, index, size) {
$.Velocity.animate(element, {
opacity: [1,0],
translateY: [0, -(index+1)]
}, {
delay: index*(duration/size/2),
duration: duration,
easing: easing
});
};
}
// Fade in mtree after classes are added.
// Useful if you have set collapsed = true or applied styles that change the structure so the menu doesn't jump between states after the function executes.
if($('.mtree').css('opacity') == 0) {
if($.Velocity) {
$('.mtree').css('opacity', 1).children().css('opacity', 0).velocity('list');
} else {
$('.mtree').show(200);
}
}
}
}(jQuery, this, this.document));
I've added a background image using CSS and :before but the image is not clickable.
Is there a way to add it on the JS so that it can be clicked as well?
I've tried to see where to add some code but actually I'm clueless, should it be between lines 29 and 37?
You can see it in: https://tester.medicalfa.gr/test/katastima/
Ok I fixed it via css, the arrows now appears like they are clickable.
The solution is to remove the code I had added:
ul.mtree.default li.mtree-open:before {
display: inline-block;
margin-left: 200px;
background: url("../images/arrow-down.svg") no-repeat center center;
background-size: 20px 20px;
}
I removed the :before as it adds the arrow behind the text and now appears after the text as it's supposed to.
The code looks like this now:
ul.mtree.default li.mtree-open {
display: block ;
background: url("../images/arrow-down.svg") no-repeat center center;
background-size: 15px 15px;
background-position:top right;
}
I want to do a something in a smaller width of screen But I have a problem. I'm creating a Responsive Navbar, So I want to show a Button when It is in small width & toggling the Menu. But when I hide the Menu in smaller width, It doesn't show the Menu in wider width Because of Hiding in jQuery ...
So I wanted to make jQuery Codes run JUST in smaller width, I wrote this But It doesn't work :
$(window).resize(function() {
if($(window).width() < '48em') {
$('.ji-toggle-btn').click(function() {
$(this).parent().find('ul').toggle();
});
}
});
The proper way to show/hide a button is with a media query in CSS:
.css example:
.ji-toggle-btn {
display: none;
}
#media (min-width: 48em) {
.ji-toggle-btn {
display: block;
}
}
.scss example:
.ji-toggle-btn {
display: none;
#media (min-width: 48em) {
display: block;
}
}
I mocked up a sample of how to do a responsive sidebar:
http://codepen.io/staypuftman/pen/dGOMYO
What you'll notice in this example is how little JS is used. Targeting a .toggle class and using css transitions will get you where you want to go. You're overthinking this approach with the JS.
Your problem is that you're assigning a behavior on smaller resolution. You practically want to assign a click event only when the window size is smaller than 48 em.
With simple words - just remove the click event:
$(window).resize(function() {
if($(window).width() < '48em') {
$('.ji-toggle-btn').parent().find('ul').toggle();
}
});
EDIT I agree with the guy above about the CSS. Those things basically should be done with media queries.
$(window).width() returns an int (screen width in pixels). In order to get that value in ems you need to divide that buy the body's font-size, then compare that with just '48' not '48em'. For example:
$(window).resize(function() {
if(($(window).width() / parseFloat($("body").css("font-size"))) < 48) {
// Do stuff here...
}
});
I am trying to have a div change its properties on a click function. Some of the properties I am changing with a call to toggleClass() which is fine and works great. However I also want to resize the div based on the size of the viewport. In order to have access to those numbers I am changing the width and height with jQuery. This command looks like this:
$('.box').click( function() {
$(this).toggleClass('box--grow', 0);
$(this).css('width', w * .9);
$(this).css('height', h * .9);
});
EDIT I want the height and width to go back to 100%.
I tried using the toggle class but that caused the entire div to disappear, and this solution doesn't work because when I click the div again the class is removed but the height is the same.
I am looking for a way to toggle this or to get the viewport width within the css. I tried both approaches but couldn't get anything to what I am looking for.
why not using CSS VH and VW values?
CSS:
.my90Class{
width: 90vw;
height: 90vh;
}
JS:
$('.box').click( function() {
$(this).toggleClass("my90Class");
});
You need to get the window size first, and then put everything into combined .ready() and .resize() functions, to make it responsive.
function myfunction() {
var w = $(window).width();
var h = $(window).height();
$('.box').click(function () {
if ($(this).hasClass('box--grow')) {
$(this).removeClass('box--grow');
$(this).css({
'width': '',
'height': ''
});
} else {
$(this).addClass('box--grow');
$(this).css({
'width': w * .9,
'height': h * .9
});
}
});
}
$(document).ready(myfunction);
$(window).on('resize', myfunction);
jsfiddle
You can check for the class with:
$(this).hasClass('box--grow')
Then to remove the class:
$(this).removeClass('box--grow');
And to add it back again:
$(this).addClass('box--grow');
The end would look like this save the original width and height before the event so you can add it back again:
var oldwidth = $('.box').css('width');
var oldheight = $('.box').css('height');
$('.box').click( function() {
if($(this).hasClass('box--grow')) {
$(this).removeClass('box--grow');
$('.box').css('width', oldwidth);
$('.box').css('height', oldheight);
} else {
$(this).addClass('box--grow');
}
});
untested but it would probably work
I have here a function and what I want to happen is to display the div first before it smoothly changes it's width.. Unfortunately what happen is that the width already changes once it appears
CSS:
#frame12{
opacity:0;
filter:alpha(opacity=0);
width:100;
}
jQuery:
function animatestamp(){
jQuery("div#frame12").css({'opacity':'1','filter':'alpha(opacity=100)'}).animate({
width:'451px'
},animatestamp);
}
Use animate on div's opacity first and then on its complete callback animate the width.
function animatestamp() {
jQuery("#frame12").animate({ //animate the opacity first
'opacity': 1,
'filter': 'alpha(opacity=100)'
}, 2000, function () { //Once it is completely visible start animating the width
$(this).animate({
'width': '451px',
}, 1000);
});
}
animatestamp();
Fiddle
For recursive you can try this:
var $frame = jQuery("#frame12");
function getWidthConfig(elem) { //get the width animate object based on current elem width
return {
'width': elem.width() > 450 ? '100px': '451px'
}
}
function getOpacityConfig(elem) {//get the opacity animate object based on current elem opacity
var opac = +elem.css('opacity');
return {
'opacity': !opac ? 1 : 0,
'filter': !opac ? 'alpha(opacity=100)' : 'alpha(opacity=0)'
}
}
function animatestamp() {
$frame.animate(getOpacityConfig($frame), 2000, function () {
$frame.animate(getWidthConfig($frame), 1000, animatestampReverse);
});
}
function animatestampReverse() {
$frame.delay(2000).animate(getWidthConfig($frame), 1000, function () {
$frame.animate(getOpacityConfig($frame), 2000, animatestamp)
});
}
animatestamp();
Fiddle
Animate opacity & filter first, then animate the width as PSL well said but also in your CSS, change "width:100;" to "width:100px;" (Add measurement unit "px") or otherwise the div's initial width would be screen width (add a border to your css to see the difference visually) and to make your js simpler and more readable, use chaining in your Javascript:
CSS:
#frame12{
opacity:0;
filter:alpha(opacity=0);
width:100px; /*Add px to avoid max screen witdth and CSS Flash */
border: solid 1px; /* to see the real div width */
}
Javascript:
function animatestamp() {
$("div#frame12")
.animate({ 'opacity': 1, 'filter': 'alpha(opacity=100)' }, 2000)
.animate({ width: '451px'}, 1000);
}
Need more code to be sure, but I'm guessing its because you have not set an explicit width on that container before applying an animation to the width property. Could try this:
function animatestamp(){
$("#frame12").css({
'opacity':'1',
'filter':'alpha(opacity=100)',
'width': $(this).width()
}).animate({
width:'451px'
}, animatestamp);
}
Or just set it in the css...
#frame12 { width: 100px; }
... and remove the 'width' from the css() above.