I'm having a strange issue, and my google-fu is failing me. I'm working on a WordPress plugin, and I'm passing variables from the settings page to the jQuery script. It's all passing perfectly fine, except that within the script, it's completely ignoring the value for the speed in slideToggle().
For the record, I'm loading a jQuery script (jQuery UI - v1.11.2): core and effects.
Here is my script:
jQuery(document).ready(function($) {
var $show_open_by_default = wp_settings.expanded;
var $showtext = wp_settings.show;
var $hidetext = wp_settings.hide;
var $speed = wp_settings.toggle_down;
var $easing = wp_settings.easing;
if($show_open_by_default != 1) { // if setting is unchecked...
$('.comment .children').hide(); // hide all children on load
}
$('.comment-list > li').each(function() {
if( $(this).find('.children').length > 0 ) {
$(this).find('.children').before('<div class="replylink"><span class="show">'+$showtext+'</span></div>');
}
});
$('.replylink').hover(function() { // when hovering the replylink...
$(this).css('cursor','pointer'); // change the cursor...
}, function() {
$(this).css('cursor','auto');
}).click(function() { // and on click...
// change the text
$(this).text( $(this).text() == $hidetext ? $showtext : $hidetext);
// animate the visibility of the children
var $nextDiv = $(this).next();
var $visibleSiblings = $nextDiv.siblings('div:visible');
if ($visibleSiblings.length == 0 ) {
$visibleSiblings.slideToggle($speed, $easing);
} else {
$nextDiv.slideToggle($speed, $easing);
}
});
});
It all works perfectly fine, except for the slideToggle() call at the end. If I place alert($speed); just before the slideToggle() call, it does, indeed, alert the correct setting just fine. However, the slideToggle ignores it and reverts to the default speed.
What's funny is, if I manually put in a value, it works just fine. But with the passed value, it ignores it. I am completely stumped on this. I've tried everything I can think of to make it pay attention to that number, but it will only do so if I hard-code it in the slideToggle() call. If it's passed, it won't pay attention to it. Am I missing something?
Any help would be appreciated. Thanks!
Just wanted to post the the solution was found - but the answer is in the comments. Basically, the passed value is a string, not numeric. So I have some conversion to do in my PHP file to be sure the value is passed correctly based on the type.
Related
I updated a website I am working on to the latest WordPress last week. None of the custom JS is working anymore and I can't work out why.
Even if I remove it in sections to try and isolate the issue, I always get 'Uncaught TypeError: $ is not a function'.
I cannot work out what has caused this to happen.
As far as I can see, all the scripts load as expected.
Unfortunately all the JS in my custom file has been acquired either from Stack Overflow or other online resources - I did not write it myself (only amended) and thus am struggling to diagnose the issue.
Any help would be appreciated
// apply effect to pages
var $headereffect = $('.hero-effect');
$headereffect.waypoint(function (direction) {
if (direction == 'down') {
$headereffect.addClass('hero-effect-animation');
} else {
$headereffect.removeClass('hero-effect-animation');
}
}, { offset:'1px' });
// apply effect to default page headers
var $headereffect = $('#page-header');
$headereffect.waypoint(function (direction) {
if (direction == 'down') {
$headereffect.addClass('hero-effect');
} else {
$headereffect.removeClass('hero-effect');
}
}, { offset:'1px' });
My wild guess is to use jQuery instead of the $ as sometimes the latter is used by other scripting libraries and this causes issues and conflicts.
So
var $headereffect = $('.hero-effect');
becomes
var $headereffect = jQuery('.hero-effect');
This will fix the current issue but others also may be raised on a later stage. Inspect your code and make sure you use a consistent jQuery reference.
Options to handle the $ issue the jQuery way can be found here. From a practical point of view, you can put jQuery into "no conflict" mode by using shortcut for jQuery. In this case "$j" instead of the default "$":
var $j = jQuery.noConflict();
$j(function(){
$j("#sidebar li a").hover(function(){
$j(this).stop().animate({
paddingLeft: "20px&"
}, 400);
}, function() {
$j(this).stop().animate({
paddingLeft: 0
}, 400);
});
});
A best practice as Wordpress suggest is to wrap your code in immediately invoked function expression, pass jQuery to it and use the $ internally like this:
( function( $ ) {
// Your code goes here
} )( jQuery );
This is a simple password checking function I messed around with for a little bit. I've tried a lot of different methods (including, but not limited to: .css(), .on('click'), .click(), .animate(), .show(), .hide(), .preventDefault() on the submit), put selectors into variables, moved around all sorts of IDs and $('input[name="s"]') and all sorts of selectors. Not sure if the function won't work, or maybe something else within the script. I've taken the function out of the $(document).ready() tree, and moved it all around inside of it. I'm sure that isn't the problem now, but I'm starting to not be sure about anything at this point.
I'm trying to get the function to hide the password textbox and submit(or is button better?) and show a textarea for news input, with a button to append the update.The appendedTo and .append() section works, but I can't seem to get the passwordcheck function to work. Sometimes it will alert me if it's wrong, but when it's right the if methods don't seem to work. Then I'll change it a few times and the alert will no longer show, nor will the if work any longer.
Any help would be appreciated, and I can provide any code snippets or chunks at request.
Function in question:
function passwordcheck() {
var $newspass = $('#newspass');
var $submitpass = $('#submitpass'); // <--- variables were at one point selectors
var $newssubmit = $('#newssubmit'); // written out, I've changed this a lot
if ($newspass.val() === 'comecorrecT') {
$submitpass.css('display', 'hidden');
$newspass.css('display', 'hidden');
$('#newsinput').css('display', 'block');
$newssubmit.css('display', 'static');
} else {
alert("Try again, please.");
}
};
Rest of the script, for reference:
$(document).ready(function(){
// billboard functions
var $billboard = $('.billboard');
$billboard.mouseenter(function(){
$(this).fadeTo('slow', 0.98);
});
$billboard.mouseleave(function(){
$(this).fadeTo('slow', 0.72);
});
var $learn = $('#learn-more');
$learn.hover(function(){
$(this).fadeTo('slow', 1);
},
function() {
$(this).fadeTo('slow', 0.6);
});
// news and updates/appendedTo
var $submitpass = $('#submitpass');
var $newssubmit = $('#newssubmit');
$submitpass.click(passwordcheck());
$newssubmit.click(function(){
$('#appendedTo').append('<div class="update">'+$('#newsinput').val()+'</div>');
// passwordcheck();
});
});
I've been working with it for a little while now, and I know you guys will have a profound explanation or two.
The way you are doing it now, you are simply passing "undefined" instead of a function (which would be what the passwordcheck function returns) as you are calling the function instead of passing a reference to it in this line:
$submitpass.click(passwordcheck());
Which should be
$submitpass.click(passwordcheck);
In the last block of your code, after
// news and updates/appendedTo
This being said, don't use client side JavaScript for authentication, the password you are checking against is visible for anyone using the site.
Try this:
function passwordcheck() {
var newspass = $('#newspass').val();
var submitpass = $('#submitpass').val();
var newssubmit = $('#newssubmit').val();
if (newspass == 'comecorrecT') {
$('#submitpass').hide();
$('#newspass').hide();
$('#newsinput').show();
} else {
alert("Try again, please.");
}
}
I seem to be having issues with programmatic opening and closing of a JQM 1.3 Panel.
EDIT: This is for JQM 1.3.x not 1.4+
It is somewhat hard to explain, so I just made a fiddle :)
There is a lot going on in the fiddle, but it is just a sample of a much larger app and conveys the issue.
How to replicate:
Go to Fiddle
On Fiddle open the Panel and go to Page Two
On Page Two open Panel and go to Page One
Try to Open the Panel now on page one, it does nothing.
Browsers Affected:
EDIT: This seems to be fixed in Chrome 30.0.1599.101 m
Chrome 28.0.1500.95 m
IE 10.0.9200.16635
Safari // Latest Ver
Android WebView (4.2.2)
Browsers NOT Affected:
Firefox 23
Opera 12.16
Link to Fiddle:
http://jsfiddle.net/q2YH3/
Link to Other Posts
https://github.com/jquery/jquery-mobile/issues/6308
http://forum.jquery.com/topic/panel-not-responding-after-page-change
EDIT: So Firefox gives me an error that neither Chrome or IE do.
When I click to go back to page one, I get:
Type Error: elem is undefined
The error is thrown by JQ 1.9.1, I trace it back to this:
A method for determining if a DOM node can handle the data expando
acceptData: function( elem ) {
// Do not set data on non-element because it will not be cleared (#8335).
if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
return false;
}
var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
// nodes accept data unless otherwise specified; rejection can be conditional
return !noData || noData !== true && elem.getAttribute("classid") === noData;
}
`
Note the :
Do not set data on non-element because it will not be cleared (#8335).
Github Issue Link:
https://github.com/jquery/jquery/pull/1232
OG Code:
$('.showMenu').on('click', function(){
$.mobile.loading('hide');
$.mobile.activePage.find('#'+$.mobile.activePage.attr('id')+'P').panel("toggle");
});
$('.btnMenuItem').on('click', function(event){
myPgActions.nav(event, function(target){
$.mobile.changePage(target);
}, false);
});
var myPgActions = {};
myPgActions = {
nav: function(event, callback, manualHash){
var PID = $.mobile.activePage.attr('id'),
target = (!!event) ? event.target.name : manualHash;
$("#"+PID+"P").panel( "close" );
if(PID != 'loading') $("#"+PID+"Iframe").hide();
if(PID == target){
$("#"+PID+"Iframe").hide('fast', function(){
$("#"+PID+"Iframe").attr('src', "");
myPgActions.update(PID, target, 'refresh', function(target){
callback(target)
});
});
}else{
this.update(PID, target, 'change', function(target){
callback(target);
});
}
},// end get
update: function(PID, target, type, updateCallback){
var ifReady = $.Deferred();
if(type == 'refresh'){
this.buildUrl(PID, function(url){
$('#'+PID+'Iframe').attr( 'src', url);
ifReady.resolve();
$.when(ifReady).then(function(){
updateCallback('#'+PID+'Iframe')
});
});
}else if(type == 'change'){
this.buildUrl(target, function(url){
$('#'+target+'Iframe').attr( 'src', url);
ifReady.resolve();
});
$.when(ifReady).then(function(){
updateCallback('#'+target);
});
}
}, // end set
buildUrl: function(page, buildCallback){
switch(page){
case 'dash':
var mobileSiteUrl = 'URL with options for iframe'
setTimeout(function(){buildCallback(mobileSiteUrl);},25);
break;
case 'local':
var mobileSiteUrl = 'URL with options for iframe'
setTimeout(function(){buildCallback(mobileSiteUrl);},25);
break;
}// End Switch
}
}// End Obj
Had the same problem, panel not showing after page changes.
Two small changes can fix that:
what I did was to change the panel from id="myPanel" to class="myPanel", then changed the call to the panel to open: $('.myPanel:visible').panel('open'); - that's it!
The problem is that the panel has to be inside of a jQuery "page", and after the transition, if you have the panel set in the target page, you actually have two (or more) panels with the same id which is wrong or same class which is fine. So you just change the id to a class and call the visible one.
Took me too long, Hope it saves time to someone else.
I played around with your code a bit. I noticed that If I put an alert inside your update function, that it fixes everything. So I researched why an alert would make a program work, and found this page.
http://ubuntuforums.org/archive/index.php/t-930002.html
"You should probably know that JavaScript evaluation is of the 'look ahead' type: the script already runs when it is still being evaluated (and while the page itself is still being evaluated). Now that is why it is recommended to dump all references to scripts in the section of your page, as it will cause the JavaScript to be fully evaluated before you (usually) can call a function (event handlers), and hence avoid silly 'undefined' errors.
Now the alert(); call has 2 effects: (1) it pops up the message box (so far, so good);.but (2) it halts the thread the JavaScript is using! However the browser's other threads will still continue to go on (HTML rendering...). So it may be one of those cases that you would benefit from a more elegant halting method, which is to only execute this (part of the) script when the document has been fully loaded;"
The solution they suggest is putting your script inside of the . Or using "stateChanged() function of the ajax http request".
Well I upvoted #A.sharif 's post, as he got the gears in my head spinning.
The problem lies in the fact that the callback of the "BuildUrl" function was executing before the URL variable was built.
I thought I had allowed ample time with 25ms but it was not. I bumped the time before the callback is executed up to 600 ms and it works fine now.
I am sure there is a more elegant solution, but this is what I got ;)
New Fiddle:
http://jsfiddle.net/t8zyQ/
What was changed was the value of 25 in the setTimeout() to 600.
Changed Code:
buildUrl: function(page, buildCallback){
switch(page){
case 'dash':
var mobileSiteUrl = 'URL with options for iframe'
setTimeout(function(){buildCallback(mobileSiteUrl);},600);
break;
case 'local':
var mobileSiteUrl = 'URL with options for iframe'
setTimeout(function(){buildCallback(mobileSiteUrl);},600);
break;
}// End Switch
I have a native <select>-element based on which I'm initializing a select2-dropdown-menu.
I bound a change-event via select2 which is called whenever the select2/select-option is changed. However, I need to fire the event even if the currently selected option is selected again.
function onSelectChange(){
alert('changed');
};
$("#select").select2().bind('change', onSelectChange);
I prepared a http://jsfiddle.net/rb6pH/1/ - if "Alaska" is currently selected and then selected again via the select2-dropdown, onSelectChange() should fire again, triggering the alert.
I have a hard time expressing myself, please ask if something isn't clear enough.
Motivated by the absolutely valid remarks by #FritsvanCampen, I sat my ass down and figured out a way myself: What I really needed was a way to access the currently selected val, even if it hadn't changed. By using select2's undocumented close-event instead of change, I can access just that like so:
function onSelectChange(event){
alert( $("#select").select2("val") );
};
$("#select").select2().bind('close', onSelectChange);
Find an updated jsFiddle at http://jsfiddle.net/rb6pH/42/
A similar question was asked here. I have made a fiddle for your question based on the code in the link.
http://jsfiddle.net/rb6pH/55/
function onSelectChange(){
alert('changed');
};
var select2 = $("#select").select2().data('select2');
select2.onSelect = (function(fn) {
return function(data, options) {
var target;
if (options != null) {
target = $(options.target);
}
if (target) {
onSelectChange();
return fn.apply(this, arguments);
}
}
})(select2.onSelect);
I think you might refer to this link, i stuck once in same situation,
Change event is not fired when the selection is changed using Select2's val() method.
The event object contains the following custom properties:
val
the current selection (taking into account the result of the change) - id or array of ids.
added
the added element, if any - the full element object, not just the id
removed
the removed element, if any - the full element object, not just the id
For more information you might refer to this.
Thanks!
I read the question and it's so close to my problem so I decided not to post another question. What I want to do is after select2 closed, a simple text input become focused but it doesn't work. please check
function onSelectChange(){
alert('closed');
$('#hey').focus();
};
$("#select").select2().bind('close', onSelectChange);
$('#hey').on('focusin)', function(){alert('in');}
http://jsfiddle.net/sobhanattar/x49F2/5/
I tried to make sure that the input become focused and it showed that the input become focused but I don't know why it doesn't show the curser
a little old question but i spent a few hours last week to find a solution.
I am using Select2 version: 4.0.5.
My working solution is this one:
$("#exampleId").on("select2:open", function() {
var checkExist = setInterval(function() {
var $selectedChoiceInsideSelect2Dropdown = $("li.select2-results__option[id^='select2-" + exampleId + "-result'][aria-selected=true]");
if ($selectedChoiceInsideSelect2Dropdown.length) {
$selectedChoiceInsideSelect2Dropdown.on("mouseup", function() {
$(this).trigger("change");
});
clearInterval(checkExist);
}
}, 100); // check every 100ms
});
It's very important to use the interval!
var prev_val = $('#select2').val();
$('#select2').blur( function() {
if( $(this).val() == prev_val )
// not changed
else {
// changed
prev_val = $(this).val();
}
});
In the end, I have decided that this isn't a problem that I particularly need to fix, however it bothers me that I don't understand why it is happening.
Basically, I have some checkboxes, and I only want the users to be able to select a certain number of them. I'm using the code below to achieve that effect.
$j( function () {
$j('input[type=checkbox].vote_item').click( function() {
var numLeft = (+$j('#vote_num').text());
console.log(numLeft);
if ( numLeft == 0 && this.checked ) {
alert('I\'m sorry, you have already voted for the number of items that you are allowed to vote for.');
return false;
} else {
if ( this.checked == true ) {
$j('#vote_num').html(numLeft-1);
} else {
$j('#vote_num').html(numLeft+1);
}
}
});
});
And when I was testing it, I noticed that if I used:
$j('input[type=checkbox]').each( function () {
this.click()
});
The JavaScript reacted as I would expect, however when used with:
$j('input[type=checkbox]').each( function () {
$j(this).click()
});
It would actually make the counter count UP.
I do realize that it isn't the most secure way to keep count using the counter, however I do have server side error-checking that prevents more than the requisite amount from being entered in the database, that being the reason that I have decided that it doesn't actually need fixing.
Edit: The $j is due to the fact that I have to use jQuery in noConflict mode...
$(this) contains a jQuery wrapper (with lots of functions) whereas this is solely the DOM object.
The fact that counter is going up gave me the clue that there is a link between checked attribute, which you are using, and firing the click event manually.
I searched Google for 'jquery checkbox click event raise' and found this link, where author faces the exact same problem and the workaround he used.
http://www.bennadel.com/blog/1525-jQuery-s-Event-Triggering-Order-Of-Default-Behavior-And-triggerHandler-.htm
On a side note, I think you can simplify your code further:
$j('input[type=checkbox].vote_item').click(
function()
{
var maxNumberOfChoices = 5;
//get number of checked checkboxes.
var currentCheckedCount = $j('input[type=checkbox].vote_item :checked');
if(currentCheckedCount > maxNumberOfChoices)
{
//It's useful if you show how many choices user can make. :)
alert('You can only select maximum ' + maxNumberOfChoices + ' checkboxes.');
return false;
}
return true;
});
this.click() calls the browser DOM method click().
$(this).click() calls the jQuery method click(), which does more than just call the browser method: see the implementation of the function trigger for details.