jQuery window resize not working properly - javascript

Pseudocode:
If the window size equal to / or greater than 768 take content from the #sidebar and enter it in the place-holder div
If the window size is less than 768, do not run the above.
My jQuery code is as following:
$(document).ready(function () {
var $window = $(window);
function checkWidth() {
//set main vars
var windowsize = $window.width();
var $sideBarContent = $('#sidebar .dummy-content');
var $placeHolder = $('#place-holder');
//perform the main check
if (windowsize >= 768 && $('#place-holder').length) {
$($sideBarContent).clone(true)
.appendTo($($placeHolder));
}
else {
$($placeHolder).hide();
}
}
// Execute on load
checkWidth();
// Bind event listener
$(window).resize(checkWidth);
});
But the problem is that at the first page load everything is performed well, but at resize and back again, the script is not doing his job. Also on each resize all the content from the sidebar, is entered several times into the placeholder (instead of once).
And my working jsfiddle.
I just do not know what I'm doing wrong.

A few problems:
Your logic to add the new items is always true (as you only check whether the element exists - it always does).
Your child check needs to be inside the width check (separate check).
You need to show the placeHolder div again!
You have some redundant $() around jQuery variables
You have jQuery variables, for all the required elements, but sometimes you do not use them.
e.g.
$(document).ready(function () {
var $window = $(window);
function checkWidth() {
//set main vars
var windowsize = $window.width();
var $sideBarContent = $('#sidebar .dummy-content');
var $placeHolder = $('#place-holder');
//perform the main check
if (windowsize >= 768) {
if (!$placeHolder.children().length) {
$sideBarContent.clone(true)
.appendTo($placeHolder);
}
$placeHolder.show();
} else {
$placeHolder.hide();
}
}
// Bind event listener and do initial execute
$window.resize(checkWidth).trigger("resize");
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/jtfv4jjt/8/
Note: Your code can be simplified further as you only need to clone once at start and then just toggle visibility of that panel.
e.g.
$(document).ready(function () {
var $window = $(window);
var $sideBarContent = $('#sidebar .dummy-content');
var $placeHolder = $('#place-holder');
function checkWidth() {
$placeHolder.toggle($window.width() >= 768);
}
// Clone at start - then hide it
$sideBarContent.clone(true).appendTo($placeHolder);
// Bind event listener and do initial execute
$window.resize(checkWidth).trigger("resize");
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/jtfv4jjt/6/
Again this can be shortened:
$(function () {
var $window = $(window);
var $sideBarContent = $('#sidebar .dummy-content');
var $placeHolder = $('#place-holder');
// Clone content at start - then hide it
$sideBarContent.clone(true).appendTo($placeHolder);
// Bind event listener and do initial execute
$window.resize(function(){
$placeHolder.toggle($window.width() >= 768)
}).trigger("resize");
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/jtfv4jjt/7/
That's all for now :)
One last point:
If you use Twitter bootstrap, you can simply decorate the panel with an appropriate class (something like visible-md) and all this will happen for you :)

Take the event listener outside the document.ready() function:
$(document).ready(function(){
...
});
$(window).resize(checkWidth);
Also, take out the checkWidth() function outside the document.ready() function.

Related

Resize one textarea with another?

I have a website with a few pages, each containing two textareas. All I'm trying to do is get it so that when the user resizes one of the textboxes, the other one sizes with it.
Here's what I've tried so far:
Attempt #1
$(document).ready(function(){
var taheight;
$('textarea').resize(function(){
taheight = $(this).height();
$('textarea').not(this).css('height',taheight);
});
});
I also tried .on('resize', function()... and some other variations before realising it couldn't be done that way on account of the fact the resize functionality on textareas is a browser control, rather than part of the DOM.
Then I found this jsFiddle: jsfiddle.net/gbouthenot/D2bZd/
I tried modifying it and came up with this:
$(document).ready(function(){
var textareaResize = function(source, dest) {
var resizeInt = null;
var thisTextArea;
var resizeEvent = function() {
dest.outerHeight(source.outerHeight());
};
source.on("mousedown", function(e) {
resizeInt = setInterval(resizeEvent, 1000/30);
thisTextArea = $(this).attr('id');
});
$(window).on("mouseup", function(e) {
if (resizeInt !== null) {
clearInterval(resizeInt);
}
resizeEvent();
});
};
textareaResize($("#" + thisTextArea), $("textarea"));
});
But that wouldn't get the id of the target textarea. I also tried thisTextArea = e.target.id, but that wouldn't work either.
Help! Where are am I going wrong?
You can do that by using jQuery UI resizable() and call the resize event from it.
$("textarea").resizable({
resize: function() {
//To get the id of the textarea being resized
var id = $(this).find('textarea').attr('id');
//You could also just put the resize function code here
}
});
jQuery UI Resizable

.scroll() is only running once

I'm trying to create a small snippet for a sticky sidebar with jQuery. For some reason, the function inside of .scroll() is only running once instead of running at every scroll event. What could I be doing wrong?
var sticky = $('#sticky');
var staticSticky = $(sticky).offset().top;
$(window).scroll(moveEl(sticky, staticSticky));
function moveEl(element, staticElToTop){
if( $(window).scrollTop() >= staticElToTop ){
$(element).css('top', $(window).scrollTop() + 'px');
}
}
See here for the entire attempt: http://codepen.io/ExcellentSP/pen/GqZwVG
The code above is not fully functional. I'm just trying to get the scroll event to work properly before I continue.
You need to wrap content of your your moveEl method into the function (to be returned for $(window).scroll()) like this:
var sticky = $('#sticky');
var staticSticky = $(sticky).offset().top;
$(window).scroll(moveEl(sticky, staticSticky));
function moveEl(element, staticElToTop) {
return function() {
if( $(window).scrollTop() >= staticElToTop ){
$(element).css('top', $(window).scrollTop() + 'px');
}
}
}
Explanation:
The key difference is that you call a function and it returns undefined by default, so it equals to $(window).scroll(undefined). Since you actually called it, you see it's fired only once which is obvious.
As soon as you return a function within moveEl method, .scroll() gets a handler, so it becomes $(window).scroll(handler). So it will work now as expected.
In doing that $(window).scroll(moveEl(sticky, staticSticky));, you ask to javascript to execute the function. You don't pass its reference.
$(window).scroll(function(){
moveEl(sticky, staticSticky);
});

Switch click and hover events based on width

I want to toggle events based on width. for mobile only click event should work. for desktop hover event should work. while page loading my code working properly when resize my code is not working.
please help me why my code is not working. Thanks in advance
$(document).ready(function(){
function forDesktop(){
$(".popover-controls div").off('click');
$(".popover-controls div").on('hover');
$(".popover-controls div ").hover(function(e){
//popup show code
});
}
function forMobile(){
console.log("mobile");
$(".popover-controls div").off('hover');
$(".popover-controls div").on('click');
$(".popover-controls div").click(function(e){
//popop show
});
}
function process(){
$(window).width() > 600?forDesktop():forMobile();
}
$(window).resize(function(){
process()
});
process();
});
Its very simple, 1st you cant write this much of code for every event. We have to come up with very simple solution, here is how it works
1st check the width of the Page in JS and assign Desktop/Mobile Class on body :
function process(){
if( $(window).width() > 600){
$("body").removeClass("mobile").addClass("desktop");
}else{
$("body").removeClass("desktop").addClass("mobile");
}
}
$(window).resize(function(){
process()
});
Now, you have execute the command for hover and click:
$(document).on('mouseover', 'body.mobile .popover-controls div',function(e){
alert("hover");
});
$(document).on('click', 'body.desktop .popover-controls div',function(e){
alert("click");
console.log("click");
});
I Hope this will work for you. :)
Check the Js fiddle Example: http://jsfiddle.net/asadalikanwal/xcj8p590/
I have just created for you, also i have modified my code
You could use a JavaScript Media Query to determine the width of the screen as detailed here.
var mq = window.matchMedia( "(min-width: 500px)" );
The matches property returns true or false depending on the query result, e.g.
if (mq.matches) {
// window width is at least 500px
} else {
// window width is less than 500px
}
First Detect the Mobiles/Tablets Touch Event:
function is_touch_device() {
return 'ontouchstart' in window // works on most browsers
|| 'onmsgesturechange' in window; // works on ie10
};
Then Try like this:
function eventFire() {
var _element = $(".popover-controls div");
// True in Touch Enabled Devices
if( is_touch_device() ) {
_element.click(function(e) { .... });
}
else {
// apply Hover Event
_element.hover();
}
}
No need to detect width of devices ;)
There is one more solution with third party and Most popular library is Modernizr
This worked for me. It's a combination of the matchMedia() functionality #Ḟḹáḿíṅḡ Ⱬỏḿƀíé shared as well setTimeout() functionality #Jeff Lemay shared at TeamTreeHouse.com
The primary thing I contributed to was the use of the .unbind() functionality. It took me quite a while to figure out that this was necessary so the .hover() and .click() functions don't cross wires.
//Add/remove classes, in nav to show/hide elements
function navClassHandler(){
if($(this).hasClass('active')){
$('.dropdown').removeClass('active');
}else{
$('.dropdown').removeClass('active');
$(this).addClass('active');
}
}
function handleNav() {
//instantanteous check to see if the document matches the media query.
const mqM = window.matchMedia('(max-width: 1025px)');
const mqD = window.matchMedia('(min-width: 1025px)');
$('.dropdown').unbind(); //necessary to remove previous hover/click event handler
if (mqM.matches) {
console.log("Handling mobile");
$('.dropdown').click(navClassHandler);
} else {
console.log("Handling desktop");
$('.dropdown').hover(navClassHandler);
}
}
// we set an empty variable here that will be used to clearTimeout
let id;
/* this tells the page to wait half a second before making any changes,
we call our handleNav function here but our actual actions/adjustments are in handleNav */
$(window).resize(function() {
clearTimeout(id);
id = setTimeout(handleNav, 500);
});
//As soon as the document loads, run handleNav to set nav behavior
$(document).ready(handleNav);

jQuery Plugin breaks with this.each

I'm writing a plugin and trying to wrap the function inside of an each method but it breaks the plugin. If the block content is not wrapped within "this.each" plugin works. I understand that in order to pass multiple selectors I need to "return this.each" or not? I also want to eliminate the need to use the selector inside the plugin e.g "#the_lead", instead use "this".
(function($) {
$.fn.scroll_lead = function (options) {
var defaults = {
speedup: 500
};
var options = $.extend({}, defaults, options);
return this.each(function () {
var $window_height = $(window).height();
var $document_height = $(document).height();
var $hide_lead;
$(window).scroll(function () {
var $scrollTop = $(window).scrollTop();
if (!$hide_lead) {
if ($scrollTop > ($document_height / 2)) {
$("#the_lead").slideDown(options.speedup);
} else {
$("#the_lead").slideUp(500, function () {
$(this).hide();
});
}
}
});
$('#hide_lead').click(function (e) {
$(this).parent().parents('div').hide();
hide_lead = true;
e.preventDefault();
});
});
};
})(jQuery);
Few things;
Assign $(this) to $this and use it inside any function inside your plugin, said in the tutorial, http://docs.jquery.com/Plugins/Authoring.
return this.each(function () {
var window_height = $(window).height();
var document_height = $(document).height();
var hide_lead;
$this = $(this);
$(window).scroll(function () {
var scrollTop = $(window).scrollTop();
if (!hide_lead) {
if (scrollTop > (document_height / 2)) {
$this.slideDown(options.speedup);
} else {
$this.slideUp(500, function () {
//$(this).hide();
});
}
}
});
$this.click(function (e) {
$(this).parent().parents('div').hide();
hide_lead = true;
e.preventDefault();
});
});
Try to avoid manipulation of parent objects inside your plugin, including $(window), and $(document).
It is ok to read properties of window and document, but if it is manipulated in your plugin, it will be maniuplated by number of times of your selector.
In your code, because you use this.each, you are binding scroll function of window several times. For example, $("div").scroll_lead() will bind 'scroll' method to window as many as tags of your document. The same applies to $(document) and all parent elements of plugin target.
If possible and it is your intention, use element scroll method, not window scroll.
To get scroll value $(el).scrollTop()
To scroll down, $(el).scrollTop(NUMBER)
To bind onScroll method, $(el).scroll( functtion() {...} )
Hope it helps
Firstly, your syntax is incorrect.
each would not exist on this as this is the context of the function, and not an element that jquery knows about.
try $(this).each which would get you closer.
remember Jquery.Each cannot iterrate over something that is not an object or array, so make sure that what you are trying to achieve makes sense.
What are you trying to achieve here?

Resize script appends object, does it over and over again

I have the following code in a JavaScript file:
$(document).ready(function() {
detectscreen();
});
$(window).resize(function(){
detectscreen();
});
function windowWidth() {
if(!window.innerWidth) {
// user is being a git, using ie
return document.documentElement.clientWidth;
} else {
return window.innerWidth;
}}
function detectscreen() {
if (windowWidth()>1280) {
$('body').append('<div id="gearsfloat"></div>');
}}
Basically, what it does is append an object to the end of the document if the width is less than 1280 pixels, however what this does is append it every single time the page is resized.
I don't think I can use the once function because it would only run it once and then the next time it is resized, it's dead. Anything I can do?
NOTE: I, in fact, DO want it to be checked on the resize of the page, but the effect is that it happens over and over again.
if (windowWidth()>1280 && !$('gearsfloat')) {
$('body').append('<div id="gearsfloat"></div>');
}
The above (by Jason) works does not work but then it won't delete it when it gets less than 1280. Is there anything I can do?
Keep track of whether the element exists or not, and add/remove it when the condition changes. That way you will only add it once, it will be removed when it shouldn't be there, and you don't do any unneccesary adding or removing:
var gearsExists = false;
function detectscreen() {
var shouldExist = windowWidth() > 1280;
if (shouldExist != gearsExists) {
if (shouldExist) {
$('body').append('<div id="gearsfloat"></div>');
} else {
$('#gearsfloat').remove();
}
gearsExists = shouldExist;
}
}
if (windowWidth()>1280 && !$('gearsfloat')) {
$('body').append('<div id="gearsfloat"></div>');
}
Check if the element already exists first?
if you dont want the function to be called when the window is resized, then why are you binding the resize function?
wont the document ready function always be called before the resize function anyway, so you are guaranteed to have your element appended?

Categories

Resources