Using jQuery/jQueryMobile, I have a link as follows:
<a href="index.html" id="HomeLink" data-role="button" data-mini="true" data-icon="home" data-iconpos="top" >Home</a>
I am trying to test various screen sizes, and if the screen width is less than 300px, I want to change:
data-iconpos="top"
to
data-iconpos="notext"
so I only get the icon. I have tried to do it with JavaScript:
var hl = document.querySelector('#HomeLink');
if ($(window).width() < 300) {
hl.setAttribute("data-iconpos", "notext");
} else {
hl.setAttribute("data-iconpos", "top");
}
But it won't work.
Question: can it be done in CSS instead.
If not: how can it be done in JavaScript?
You can't really set a data attribute with CSS as far as I know, but since you're already using jQuery, why not try it all the way :
$('#HomeLink').data('iconpos', ($(window).width() < 300 ? 'notext' : 'top') );
Remember to wrap that in document ready!
You can do this way altering your code:
var hl = $('#HomeLink');
if ($(window).width() < 300) {
hl.data("iconpos", "notext");
} else {
hl.data("iconpos", "top");
}
with .attr():
var hl = $('#HomeLink');
if ($(window).width() < 300) {
hl.attr("data-iconpos", "notext");
} else {
hl.data("data-iconpos", "top");
}
Try to wrap the code in window resize event, eg:
$(window).resize(function () {
check();
})
$(function () {
check();
})
function check() {
if ($(window).width() < 300) {
$('#HomeLink').attr('data-iconpos', 'notext');
} else {
$('#HomeLink').attr('data-iconpos', 'top');
}
}
I would like to suggest using a different approach.
The data-iconpos="top" looks a bit out of place to me here. I have a feeling (perhaps I'm wrong) that you're attempting to inline your styling into the HTML.
Why not try media queries?
#media screen and (max-width: 300px) {
#HomeLink {
/* styling for HomeLink when screen width is less than 300px */
}
}
This is a CSS-only solution. It works if the user decides to resize the screen after the page has loaded. Try resizing the "Result" frame in this jsfiddle and notice the color of the link changing.
Suggested reading:
http://alistapart.com/article/responsive-web-design
https://developer.mozilla.org/en-US/docs/CSS/Media_queries
And here are the docs on media queries: http://www.w3.org/TR/css3-mediaqueries/
Warning: mind ahem, IE below 9, ahem...
Related
I want to change the logo of my navbar on scroll using css. It already changes color on scroll using the .affix class provided by bootstrap.
<img class="limg" src="images/firstlogo.png" />
Only way i found how to do this was:
#custom-nav.affix .limg{
content: url(../images/secondlogo.png);}
which works perfectly on chrome. However it doesnt work on Firefox / IE / Microsoft Edge.
There seems to be a solution using ::before and ::after prefixes but those didnt work for me.
It could be caused by the following JS code which implements the affix class on scroll.
$(window).scroll(function() {
if ($(".navbar").offset().top > 50) {
$('#custom-nav').addClass('affix');
$(".navbar-fixed-top").addClass("top-nav-collapse");
} else {
$('#custom-nav').removeClass('affix');
$(".navbar-fixed-top").removeClass("top-nav-collapse");
}
});
If so, is there anyway i can change that <img src""> using JS when affix activates ?
Just change your image src attribute in scroll callback:
var startImg = "images/firstlogo.png",
scrollImg = "images/secondlogo.png",
$img = $('.limg');
$(window).scroll(function() {
if ($(".navbar").offset().top > 50) {
$('#custom-nav').addClass('affix');
$(".navbar-fixed-top").addClass("top-nav-collapse");
// Set scrolling src
$img.attr('src', scrollImg);
} else {
$('#custom-nav').removeClass('affix');
$(".navbar-fixed-top").removeClass("top-nav-collapse");
// Set default image src
$img.attr('src', startImg);
}
});
Example with timeout
As mentioned bellow, it may cause some performance problems because of many calls to DOM elements, so heres improved version with timeout and cached DOM vars:
var startImg = "images/firstlogo.png",
scrollImg = "images/secondlogo.png",
$navBar = $(".navbar"),
$customNav = $('#custom-nav'),
$navBar = $(".navbar-fixed-top"),
$img = $('.limg'),
timeout;
$(window).on('scroll', function() {
if (timeout) clearTimeout(timeout)
// Use timeout to not call function immediately
timeout = setTimeout(function() {
if ($navBar.offset().top > 50) {
$customNav.addClass('affix');
$navBar.addClass("top-nav-collapse");
// Set scrolling src
$img.attr('src', scrollImg);
} else {
$customNav.removeClass('affix');
$navBar.removeClass("top-nav-collapse");
// Set default image src
$img.attr('src', startImg);
}
}, 250)
});
content property should only works in ::before and ::after pseudoelements. If it's working on Chrome this way, Chrome has a bug (as usual).
Write as this:
.affix .limg::before {
content: url(../images/secondlogo.png);
}
It should work in all browsers.
More info:
MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/content
CSSTricks: https://css-tricks.com/almanac/properties/c/content/
I found a question/post on this site that works great upon first looking at it, until I need it to do more, and I have played with it and have not found a solution yet as to get it to do what I need it to do.
I am building a site for a client so I need it to be easy to operate in terms of if the client wants to change the actual order of things, so building a ul/li list on the back end within the theme is not an option, unless there is an easy way for me to modify the functions.php and change the way the menu tab is set up.
Here is my javascript coding, the menu is an actual wordpress menu.
jQuery(document).ready(function() {
jQuery("ul#menu-primary-items").find("li:contains('Home')").hide(); // hides home from navigation
var position = jQuery("ul#menu-primary-items li").length-1;
var i = 0;
jQuery('ul#menu-primary-items li').each(function() {
if(i == position/2) {
jQuery(this).after('the img src code is in here');
}
i++;
});
});
On full page width I need it to look like
Link | Link | Link | LOGO IMG | Link | Link |Link
On media width (the themes #media max-width is 999px) I need it to be a drop down style wordpress box with
LOGO IMG
WP "MENU" button
Link
Link
Link
Link
Link
Link
Instead of it displaying as the above, it shows as
WP "MENU" button
Link
Link
Link
LOGO IMG
Link
Link
Link
Check media in JQuery code, to set LOGO position:
jQuery(document).ready(function() {
jQuery("ul#menu-primary-items").find("li:contains('Home')").hide(); // hides home from navigation
var position = jQuery("ul#menu-primary-items li").length-1;
var i = 0;
/* check media here */
var isMedia999=false;
isMedia999 = (window.width() < 1000); //true if max width is <=999px
/* chek is done */
if( ! isMedia999)
jQuery('ul#menu-primary-items li').each(function() {
if(i == position/2) {
jQuery(this).after('the img src code is in here');
}
i++;
});
else jQuery('ul#menu-primary-items li').each(function() {
if(i == 0) { // <== first position if max width 999px
jQuery(this).after('the img src code is in here');
}
i++;
});
});
Of course this wont be actualized.refreshed on resize, so you could do:
jQuery(document).ready(function() {
myfunc();
windows.resize(myfunc());
});
function myfunc(){
jQuery("ul#menu-primary-items").find("li:contains('Home')").hide();
var position = jQuery("ul#menu-primary-items li").length-1;
var i = 0;
/* check media here */
var isMedia999=false;
isMedia999 = (window.width() < 1000); //true if max width is <=999px
/* chek is done */
if( ! isMedia999)
jQuery('ul#menu-primary-items li').each(function() {
if(i == position/2) {
jQuery(this).after('the img src code is in here');
}
i++;
});
else jQuery('ul#menu-primary-items li').each(function() {
if(i == 0) { // <== first position if max width 999px
jQuery(this).after('the img src code is in here');
}
i++;
});
});
}
Quite better: Use CSS and 2 logos.
1 logo is hidden for a media width > 999px, the 2nd is hidden for media <= 999px width.
#media max-width is 999px {
.logo#wide { display:none; }
.logo#tiny { display:inline; }
}
#media min-width is 1000px {
.logo#wide { display:inline; }
.logo#tiny { display:none; }
}
EDIT: JQuery :
jQuery(document).ready(function() {
jQuery("ul#menu-primary-items").find("li:contains('Home')").hide(); // hides home from navigation
var position = jQuery("ul#menu-primary-items li").length-1;
var i = 0;
jQuery('ul#menu-primary-items li').each(function() {
if(i == 0) {
//put logo tiny here for media maxwidth 999px
}
if(i == position/2) {
// put logo wide here for media minwidth 1000px
}
i++;
});
});
Does something like this could work ?
#media(max-width:whateveryouwant px)
{
.logo{
float:right;
}
}
An other approach would be to move the element threw the DOM.
You can achieve this with jQuery :
if((window).width() <= sizeYouWant){
$('.logo').insertBefore('#FirstElement');
}
I have this function that moves a HTML element around the DOM based on whether the window size is less than 640px or more. I'm moving the image with prepend and append, but because the function fires every time the window is resized I think I'm asking for performance issues.
The code:
function moveDealsImage() {
var mobile_width = 640;
var wi = $(window).width();
if (wi < mobile_width) {
$( ".deals-header" ).prepend( $("div.htp") );
} else {
$( ".deals-header" ).append( $("div.htp") );
}
}
window.addEventListener("resize", moveDealsImage);
moveDealsImage();
I need to keep the listener in there.
Is there a way to do that, but then only prepending/appending the element once each time that the if or else statements become true? (instead of it happening on every pixel change)
There are a few things that you can do to optimize this.
A first option is to only execute your moveDealsImage function when the state changes from mobile to desktop or reverse. All the other resizes can just be ignored.
This can be accomplished by using something like following code:
var mobile_width = 640;
var is_mobile = (window.innerWidth <= mobile_width);
function moveDealsImage(e) {
// Only execute the function when then state changes from mobile to desktop or reverse
if(
! is_mobile && window.innerWidth > mobile_width ||
is_mobile && window.innerWidth <= mobile_width
)
return;
// Update state
is_mobile = (window.innerWidth <= mobile_width);
console.log('your code here');
}
window.addEventListener("resize", moveDealsImage);
moveDealsImage();
Another and better solution would be to use CSS media queries. This can be done with the following CSS and HTML.
.desktop-deals-header {
display: block;
}
.mobile-deals-header {
display: none;
}
#media only screen
and (max-width : 640px) {
.desktop-deals-header {
display: none;
}
.mobile-deals-header {
display: block
}
}
and in your HTML you add two headers, one for desktop and one for mobile.
<div class="mobile-deals-header">Mobile header</div>
<div class="desktop-deals-header">Desktop header</div>
I have a question concerning jQuery's scrollTop functionality, and it's ability to toggle a class based on the amount of vertical scroll.
What I am trying to accomplish is on any page with a "section.banner" class, that after you scroll past the banner a class is applied to the body tag. This will allow me to change the fill colors of several SVGs that are in the site's header, as well as a fixed positioned side nav that is for pagination.
I am terrible at javascript, and have been stuck searching and trying to get this for hours. any help will be greatly appreciated. Here's the code that I'm working with now (CodeKit is telling me it is wrong, which I am not surprised). The value of 200 is just a placeholder and will be calculated by the height of a fluid image. Full disclosure, I have no idea if the brackets and parenthesis are correct.
// Header/Fixed Pagination Banner Scroll Recoloriing (toggle class)
// Check If '.banner' Exists
if( $('section.banner').length > 0) {
$('body').scrollTop(function)()
{
if $(window).scrollTop >= 200 {
$('body').toggleClass('downtown');
return false;
}
}
}
Try something like this :
if( $('section.banner').length > 0) {
$(window).scroll(function() {
{
if ($(window).scrollTop() >= $('section.banner').scrollTop()) {
$('body').toggleClass('downtown');
return false;
}
});
}
UPDATE
There was little mistake in my code : http://jsfiddle.net/t2yp15hq/
var top = $('section.banner').position().top;
if($('section.banner').length > 0) {
$(window).scroll(function() {
if ($(this).scrollTop() >= top) {
$('body').addClass('downtown');
}
else
{
$('body').removeClass('downtown');
}
});
}
It does not work with toogleClass, the background is flashing.
UPDATE
http://codepen.io/anon/pen/wBWzXy
The solution is to recalculate the top when the window is resized :
$(window).resize(function(){
top = $('section.story-intro').offset().top - 90;
});
I'm having a trouble debugging a site that's not acting very responsively. I have media queries like so:
#media (min-width: 768px) and (max-width: 992px)
{
.radio-page {
height: 1470px;
}
}
#media (min-width: 993px) and (max-width: 1199px)
{
.radio-page {
height: 1525px;
}
}
(There are a few more breaks at larger screen dimensions but I don't think they are relevant)
I haven't specified a height for this class at dimensions less than 768, instead opting for the following javascript/jquery:
function confirmer() {
if ($(window).innerWidth() < 767) {
var inHeight = $('.iright-4 p').offset().top +
$('.iright-4 p').height() - $('.inner-radio').offset().top;
var outHeight = inHeight + $('.inner-radio').offset().top - 42;
$('.inner-radio').css('height', inHeight + 20);
$('.radio-page').css('height', outHeight + 50);
}
// debug code to report element height
console.log('radio-page is ' + $('.radio-page').css('height'));
}
$(document).ready(function() {
confirmer();
$(window).resize(confirmer);
});
All is well when it loads. The problem occurs specifically when the window is resized from below 767px into something higher. For some reason the media queries no longer change the height value of the .radio-page element, despite the javascript changed being isolated to < 767px. .radio-page stays at exactly whatever height it was when the resize passed the threshold.
Also, I have a suspicion that the confirmer function is being disabled altogether when the window is > 767px, because I'm losing console updates. All is well when I re re-size to < 767px (the jquery operates as intended).
Any help is most appreciated,
SOLUTION
function confirmer() {
if ($(window).innerWidth() < 767) {
...
} else {
$('.inner-radio').css('height', '');
$('.radio-page').css('height', '');
}
...
When the javascript code sets your elements to have a specific height at < 767px, it is changing the style attribute of those elements. When you resize to 767 px or above, your CSS is trying to take over for the javascript, but that style attribute defining the height is still there. One possible solution is to clear it in your code:
function confirmer() {
if ($(window).innerWidth() < 767) {
var inHeight = $('.iright-4 p').offset().top +
$('.iright-4 p').height() - $('.inner-radio').offset().top;
var outHeight = inHeight + $('.inner-radio').offset().top - 42;
$('.inner-radio').css('height', inHeight + 20);
$('.radio-page').css('height', outHeight + 50);
}else{
$('.inner-radio').css('height', '');
$('.radio-page').css('height', '');
}
// debug code to report element height
console.log('radio-page is ' + $('.radio-page').css('height'));
}
$(document).ready(function() {
confirmer();
$(window).resize(confirmer);
});
As per the jQuery docs on $.css():
Setting the value of a style property to an empty string — e.g. $(
"#mydiv" ).css( "color", "" ) — removes that property from an element
if it has already been directly applied, whether in the HTML style
attribute, through jQuery's .css() method, or through direct DOM
manipulation of the style property. It does not, however, remove a
style that has been applied with a CSS rule in a stylesheet or
element.
In regards to losing console updates, I cannot answer that part of the question. Perhaps you are getting updates, but because the height value is the same, your browser recognizes them as identical messages and collapses them into one? Check if there is a small number next to your message. Here's an example from Chrome: