Javascript click event doe not work on wordpress - javascript

I need to call a function by clicking on some elements.
I have tried several ways but it seems that it does not want to fire.
the element in question is generated by the "quiz master and survey" plugin on wordpress.
Anyone have any idea what the problem might be? Thanks in advance!
window.onload = function() {
document.querySelectorAll('.qsm_check_answer').addEventListener("click",function(e){
var correctInfo = document.querySelector('#correct-info');
correctInfo.classList.add("d-none");
});
};
OR
document.querySelectorAll(".qsm_check_answer").addEventListener("click", function () {
document.querySelector("#correct-info").style.display = "none";
});
OR
window.onload = function () {
var checkboxQ = document.querySelectorAll(".qsm_check_answer");
checkboxQ.onclick = function () {
var correctInfo = document.querySelector("#correct-info");
correctInfo.classList.add("d-none");
};
};
Screenshot of Dom:

querySelectorAll returns all elements in the document that matches the selector.
You need to access the elements with an index:
document.querySelectorAll(".qsm_check_answer")[0]
Here is a link to more info on MDN.

Related

How to trigger ready event on JQuery chosen plugin?

I am trying to bind an liszt:ready event of my list, to be invoked once that the list has been initialized by chosen.
I follow the steps that here are describing without any success.
This is my code:
var initPreferredCollaboratorChosen = function () {
$("#preferredCollaboratorChosenId").chosen({width: "95%"}).trigger("chosen:ready");
};
var initListener = function () {
$("preferredCollaboratorChosenId").on("chosen:ready", function(){
alert("Hey, I am ready!");
});
initPreferredCollaboratorChosen()
};
I try with "liszt:ready" instead "chosen:ready" as well.
Can anyone that has work with this plugin tell me how make it?.
Regards.

How do I make my click catcher work?

I'm trying to create a simple click catcher where if you click .image-class the javascript will take the href from another element with a class name of .btn and send you to it's destination. Though I keep getting errors on lines 7 & 10 saying that undefined is not a function. How do I make this work?
<script>
var ClickCatcher=
{
init:function(){
var link = jQuery('.btn')[1].href;
var imgCatch = jQuery('.image-class');
imgCatch.addEventListener("click", ClickCatcher.clickListener, false);
},
clickListener:function(){
window.location = link;
}
};
ClickCatcher.init();
</script>
You can do this with jquery with a simple click event
jQuery('.image-class').on('click', function (){
window.location = jQuery('.btn').eq(1).attr('href');
});
But if you still want to write in the way you have you can do:
var ClickCatcher = {
init: function () {
jQuery('.image-class').on('click', function (){
window.location = jQuery('.btn').eq(1).attr('href');
});
}
};
ClickCatcher.init();
Just make sure to fire the init method after dom load.
update: One issue with it is that you have coded your target etc in the code rather then pass it, so its going to be hard to reuse, you'd be better off doing:
var ClickCatcher = {
init: function ($button, loc) {
$button.on('click', function (){
window.location = loc;
});
}
};
ClickCatcher.init(jQuery('.image-class'), jQuery('.btn').eq(1).attr('href'));
That way the internal working is seperate from the dom (as you are passing the dom dependencies to the function.
#atmd showed a very good way of doing this. If you just want to know what your mistake was though. It is wa an error in your jQuery stament to get the btn href
jQuery('.btn')[1].href
you need to call the attr function and then get the href attr. and use .eq(1) to reduce the set to the first btn
jQuery('.btn').eq(1).attr('href);

Scroll to bottom of page after get request AngularJs

I'm familiar with using something like:
$scope.gotoBottom = function(){
$location.hash('bottom');
$anchorScroll();
}
and this works.. yet what I'm seeing is an issue when retrieving data that's being used in an ng-repeat and attempting to resize when that data comes in.
Example (in controller):
users.get({userList:$routeParams.conversationId}, function(data){
$scope.userList = data;
$scope.gotoBottom();
})
The gotoBottom method is firing to fast, while the ng-repeat is looking on $scope.userList and buidling it's table based off that.
I want to be able to toggle gotoBottom after that list has been remade (or whenever it's modified). Is there a better way to achieve this?
Thank you!
You can use $watch listener to fire gotoBotton when an AngularJs variable change.
$scope.ActivityList = new Array();
$scope.$watch("ActivityList", function () {
$scope.$evalAsync(function () {
$scope.DoSomething();
});
}, true);
$scope.DoSomething = function () {
$(function () {
//$scope.gotoBottom();
});
};
Also you can run scrolling bottom after page is loaded
angular.element($window).bind('load',
function() {
var element = document.getElementById("messages-list").lastElementChild;
element.id = "bottom";
/*-------------*/
$location.hash('bottom');
$anchorScroll();
}

Refactoring Code

Let's say I have the following code:
$(function () {
$(".buy-it-now.ribbon").click(function () {
$(".bid-to-beat.ribbon.active").removeClass("active");
$(".bid-to-beat.ribbon").addClass("inactive");
$(".buy-it-now.ribbon.inactive").removeClass("inactive");
$(".buy-it-now.ribbon").addClass("active");
$(".bid-now").hide();
$(".buy-now").show();
$(".add-to-cart").hide();
})
$(".bid-to-beat.ribbon").click(function () {
$(".buy-it-now.ribbon.active").removeClass("active");
$(".buy-it-now.ribbon").addClass("inactive");
$(".bid-to-beat.ribbon").removeClass("inactive");
$(".bid-to-beat.ribbon").addClass("active");
$(".buy-now").hide();
$(".bid-now").show();
$(".add-to-cart").show();
});
});
It is a simple function that allows for multiple UI related things to happen on the front-end of a site I am working on. I am fairly (very) new to jQuery and JavaScript in general and am learning about refactoring and making my code more condensed now. The way I currently write code is sort of line per thought I have. So my question is how would an experienced developer write this same code? Or rather, how could I refactor this code?
Try the following:
$(function () {
var $handlers = $('.buy-it-now.ribbon, .bid-to-beat.ribbon');
$handlers.click(function() {
$handlers.toggleClass("active inactive");
var $elements = $(".bid-now, .add-to-cart"),
$buyElement = $(".buy-now");
if($(this).is('.buy-it-now.ribbon')) {
$elements.hide();
$buyElement.show();
} else {
$elements.show();
$buyElement.hide();
}
});
});
This question would be better suited for codereview, but yes it can be condensed a little using method chaining.
$(function () {
$(".buy-it-now.ribbon").click(function () {
$(".bid-to-beat.ribbon").removeClass("active").addClass("inactive");
$(".buy-it-now.ribbon").removeClass("inactive").addClass("active");
$(".bid-now").hide();
$(".buy-now").show();
$(".add-to-cart").hide();
})
$(".bid-to-beat.ribbon").click(function () {
$(".buy-it-now.ribbon").removeClass("active").addClass("inactive");
$(".bid-to-beat.ribbon").removeClass("inactive").addClass("active");
$(".buy-now").hide();
$(".bid-now").show();
$(".add-to-cart").show();
});
});
You could condense it further by pre selecting the elements and caching them in variables before the click events as long as no elements are added or removed during the life of the page.
As your code it is you can combine some of the selectors into a single line. And also because your elements looks to be static you can cache them into a variable and use them later as it reduces the number of times a element is looked up in the DOM reducing the accessing time..
Also you can limit the scope of these variables or selectors by encasing them in an object or a closure..
Maybe something in these lines..
$(function () {
cart.init();
});
var cart = {
elems : {
$buyRibbon : null,
$bidRibbon : null,
$bidNow: null,
$buyNow: null,
$addToCart: null
},
events : {
},
init : function() {
this.elems.$buyRibbon = $(".buy-it-now.ribbon");
this.elems.$bidRibbon = $(".bid-to-beat.ribbon");
this.elems.$bidNow = $(".bid-now") ;
this.elems.$buyNow = $(".buy-now") ;
this.elems.$addToCart = $(".add-to-cart") ;
this.events.buyClick();
this.events.bidClick();
}
};
cart.events.buyClick = function() {
cart.elems.$buyRibbon.on('click', function(){
cart.elems.$bidRibbon.removeClass('active').addClass('inactive');
cart.elems.$buyRibbon.removeClass('inactive').addClass('active');
cart.elems.$bidNow.hide();
cart.elems.$buyNow.show();
cart.elems.$addToCart.hide();
});
}
cart.events.bidClick = function() {
cart.elems.$bidRibbon.on('click', function(){
cart.elems.$buyRibbon.removeClass('active').addClass('inactive');
cart.elems.$bidRibbon.removeClass('inactive').addClass('active');
cart.elems.$bidNow.show();
cart.elems.$buyNow.hide();
cart.elems.$addToCart.show();
});
}
So basically in here your whole cart is a object ..And the cart has different properties which are related to this.. You follow the principles of object oriented programming here..
Using closures I heard gives you better design limiting the scope of your code..
Might I suggest something like this:
$(function () {
var buyNowButton = $('buy-it-now.ribbon'),
bidToBeatButton = $('.bid-to-beat.ribbon'),
buyNowEls = $('.buy-now'),
bidToBeatEls = $('.bid-now,.add-to-cart');
var toggleButtons = function(showBuyNow){
buyNowButton.toggleClass('active', showBuyNow);
bidToBeatButton.toggleClass('active', !showBuyNow);
buyNowEls.toggle(showBuyNow);
bidToBeatEls.toggle(!showBuyNow);
}
buyNowButton.click(function(){ toggleButtons(true) });
bidToBeatButton.click(function(){ toggleButtons(false) });
});
You could save a some lines by removing the selectors at the start and just do the selection in place, if the saved space would be more important than the minor performance hit. Then it would look like this:
$(function () {
var toggleButtons = function(showBuyNow){
$('buy-it-now.ribbon').toggleClass('active', showBuyNow);
$('.bid-to-beat.ribbon').toggleClass('active', !showBuyNow);
$('.buy-now').toggle(showBuyNow);
$('.bid-now,.add-to-cart').toggle(!showBuyNow);
}
$('buy-it-now.ribbon').click(function(){ toggleButtons(true) });
$('.bid-to-beat.ribbon').click(function(){ toggleButtons(false) });
});
The first version selects the elements once and holds them in memory; the second selects them each time the button is clicked. Both solve the problem I believe would occur with the selected answer where clicking the same button twice would cause the .active and .inactive classes to get out of sync with the shown/hidden elements.

Html div on load event for a dynamically added div element

How i can make some thing like this?
<div id='myDiv' onload='fnName()'></div>
can't use
window.onload = function () {
fnName();
};
or
$(document).ready(function () {fnName();});
the div element is dynamic. The div content is generated by xml xsl.
Any ideas?
You can use DOM Mutation Observers
It will notify you every time the dom changes, e.g. when a new div is inserted into the target div or page.
I'm copy/pasting the exmple code
// select the target node
var target = document.querySelector('#some-id');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true }
// pass in the target node, as well as the observer options
observer.observe(target, config);
// later, you can stop observing
observer.disconnect();
The onload attribute probably wouldn't fire on the <div> if you're injecting it dynamically (as the document is likely already loaded, but maybe it'd still work...?). However you could either poll for the element by simply doing something like this (similar to YUI's onContentAvailable):
// when the document has loaded, start polling
window.onload = function () {
(function () {
var a = document.getElementById('myDiv');
if (a) {
// do something with a, you found the div
}
else {
setTimeout(arguments.callee, 50); // call myself again in 50 msecs
}
}());
};
Or you could change the markup (I know nothing about XSL) to be something like this:
Earlier on in the page:
<script type="text/javascript">
function myDivInserted() {
// you're probably safe to use document.getElementById('myDiv') now
}
</script>
The markup you generate with XSL:
<div id="myDiv"></div>
<script type="text/javascript">
myDivInserted();
</script>
It's a bit hacky but it should work.
If you're not already using jQuery there's no reason to start using it just for this, you can write:
window.onload = function () {
fnName();
};
You could use jQuery. The following code would be place in your <head> tags.
$(document).ready(function() {
// Your fnNamt function here
});
EDIT
Kobi makes a good point
You could also write
$(document).ready(function(){fnNamt();});,
or more simply,
$(document).ready(fnNamt);, or even
$(fnNamt)
Without jQuery with plain JS eg:
<script type="text/javascript">
function bodyOnLoad() {
var div = document.getElementById('myDiv');
// something with myDiv
...
}
</script>
<body onload="bodyOnLoad()">
....
<div id='myDiv'></div>
....
</body>
I had the same Issue, and after searching I found this.
In my case, the javascript appends the head of the index html to load a tab content html file, and onload I want to add that tab to the dom, display it and make other js stuff to change the tabs style.
I added the line with .onload = function(event) {...}
var link = document.createElement('link');
link.rel = 'import';
link.href = 'doc.html'
link.onload = function(event) {...};
link.onerror = function(event) {...};
document.head.appendChild(link);
This worked like a charm, and maybe it helps some other researcher :)
I found it on HTML5 Imports: Embedding an HTML File Inside Another HTML File
How about using jQuery/ready(..) for this?
Like here: http://api.jquery.com/ready#fn
In the context of your question,
$(document).ready(function () {fnNamt();});
I would suggest you to use jQuery.
Steps:
1. Download Jquery library from here http://code.jquery.com/jquery-1.5.min.js .
2. in your HTML, head section create a script tag and use this code below.
$(document).ready(function() {
// write your code here..
});
I'd suggest circle-style func:
SwitchFUnc = false;
function FuncName(div_id) {
var doc = window!=null ? window.document : document;
var DivExists = doc.getElementById(div_id);
if (DivExists) {
//something...
SwitchFunc = true; //stop the circle
}
}
while (SwitchFunc!=true) {
FuncName('DivId');
}

Categories