I am an Apprentice and never worked with Javascript.
My Javascript function calls a popup. This works on the first button but doesn't work on all the following and since the application is constantly adding buttons(same class) I cannot hardcode. I guess ther will be a solution with JQuery...
("open") and ("openPopupUseExisting") are the two buttons.
<script type="text/javascript">
window.onload = function () {
document.getElementById('blackout').addEventListener('click', function () {
document.getElementById('popup').className = "";
document.getElementById('blackout').className = "";
document.getElementById('popupUseExisting').className = "";
}, false);
document.getElementsByClassName("open")[0].addEventListener('click', function () {
document.getElementById('popup').className = 'visable';
document.getElementById('blackout').className = 'visable';
}, false);
document.getElementsByClassName("openPopupUseExisting")[0].addEventListener('click', function () {
document.getElementById('popupUseExisting').className = 'visable';
document.getElementById('blackout').className = 'visable';
}, false);
document.getElementsByClassName("close")[0].addEventListener('click', function () {
document.getElementById('popup').className = "";
document.getElementById('blackout').className = "";
document.getElementById('popupUseExisting').className = "";
}, false);
};
</script>
document.getElementsByClassName("close")[0]
See that 0?
getElementsByClassName returns an array-like object. You are getting the first item off it.
Loop over it with a for loop.
Friend, you don't need to add an entire library just in order to bind dynamically added elements.
You can bind the document for click event, and then check if the clicked element is the one you want. It prevent dynamically added elements to be unbound, since it aims for the entire document.
document.addEventListener('click', function (e) {
if (e.target.classList.contains('blackout')) {
// your fancy magic with .blackout
} else if (e.target.classList.contains('open')) {
// your fancy magic with .open
}
}, false);
If you really want to use jQuery, as you ordered, it's quite simple, use the on method
$('.open').on('click', function(){
// your fancy magic with .open
});
Related
So I have the following jQuery code that I've built out that checks whether a on change event has been triggered on #rtk5 and then either removes or adds the 'required' attribute.
Works perfectly in jQuery:
// Make checkbox textboxes not required unless checked
$(document).ready(function() {
$('#rtk5').change(function() {
if ($('.rtk5ReqField').attr('required')) {
$('.rtk5ReqField').removeAttr('required');
}
else {
$('.rtk5ReqField').attr('required','required');
}
});
});
I would like to convert it to JavaScript with a function call, but I can't seem to figure out how to properly do it.
Error:
TypeError: rtk5req.getAttribute is not a function
Here is my attempt:
var rtk5req = document.getElementsByClassName('rtk5ReqField');
function rtk5Required() {
rtk5req.addEventListener('change', (e) => {
if (rtk5req.getAttribute('required')) {
rtk5req.removeAttribute('required');
} else {
rtk5req.getAttribute('required', 'required');
}
});
}
rtk5req.addEventListener('change', rtk5Required());
document.addEventListener('DOMContentLoaded', rtk5Required);
rtk5Required();
Updated code: Removed the repetitive change call
var rtk5req = document.getElementsByClassName('rtk5ReqField');
function rtk5Required() {
if (rtk5req.getAttribute('required')) {
rtk5req.removeAttribute('required');
} else {
rtk5req.getAttribute('required', 'required');
}
}
rtk5req.addEventListener('change', rtk5Required());
document.addEventListener('DOMContentLoaded', rtk5Required);
rtk5Required();
Updated code #2:
Thanks all for all the hard work, there's one small issue that I'm still experiencing and had to make some tweaking - When I uncheck the checkbox, it doesn't remove the required tag placed on rtk5Declaration from which it did in the jQuery.
var rtk5_selection = document.getElementById('rtk5');
document.addEventListener('DOMContentLoaded', () => {
rtk5_selection.addEventListener('change', () => {
if (rtk5_selection.getAttribute('required')) {
document.getElementById('rtk5Declaration').removeAttribute('required');
} else {
document.getElementById('rtk5Declaration').setAttribute('required', 'required');
}
});
});
Thanks so much all!
Since you only have one element you should be using its ID instead of its class, and avoiding the complication caused by document.getElementsByClassName returning a pseudo-array of elements instead of a single element.
NB: use setAttribute to change an attribute's value, or better yet (as shown in the code below) use the direct boolean property that mirrors the element's attribute.
document.addEventListener('DOMContentLoaded', () => {
const rtk_sel = document.getElementById('rtk5');
const rtk_dec = document.getElementById('rtk5Declaration');
rtk_sel.addEventListener('change', () => {
rtk_dec.required = !rtk_sel.checked;
});
});
Thanks all for the contribution, below is the working version which I have tweaked:
var rtk5_selection = document.getElementById('rtk5');
var rtk5declaration = document.getElementById('rtk5Declaration');
function rtd3Declaration() {
if (!rtk5_selection.checked) {
rtd3declaration.removeAttribute('required');
} else {
rtd3declaration.setAttribute('required', 'required');
}
}
rtk5_selection.addEventListener('change', rtd3Declaration);
document.addEventListener('DOMContentLoaded', rtd3Declaration);
rtd3Declaration();
Here is the block of code I want to replace:
$(document).ready(function () {
$(".button-purple").click(function () {
interval = $(this).attr('id');
name = $(this.attr('name');
if(Number($(this).val()) === 0) {
if(name == 'static') {
do this
}
else {
do this
}
}
else {
do this
}
});
});
I can't find any documentation on trying to replace the function since it's unnamed though. Is it possible to replace the entire javascript file + delete the line loading it / insert my own script? Would really appreciate any help I can get.
If you just want to remove the click event handler, then simply say
var $element = $(".button-purple");
$element.off('click');
If you want to Remove all the event handlers, then you'll first have to find out what all event handlers are present and then remove them iteratively.
var element = $element[0]; //Make sure the element is a DOM object and not jQuery Object.
// Use this line if you're using jQuery 1.8+
var attachedEvents = $._data(element,'events');
// Use this line if you're using jQuery < 1.8
var attachedEvents = $(element).data('events'); //Here you can also replace $(element) with $element as declared above.
for(var event in attachedEvents){
$element.off(event);
}
UPDATE:
You can simply add your own event handler (using .on() API) after you're done removing all the required existing handlers.
Just define your function.
function yourFunction(){ /* your code */};
$element.on('click', yourFunction);
Update 2:
Since you just want to remove the click event handler, this is the simplest code that will serve your purpose.
$(".button-purple").off('click').on('click', yourFunction);
I'm not aware of tampermonkey, but you can try this:
function chickHandler() {
interval = $(this).attr('id');
name = $(this.attr('name');
if (Number($(this).val()) === 0) {
if (name == 'static') {
do this
} else {
do this
}
} else {
do this
}
}
}
function onReadyHandler() {
$(".button-purple").click(chickHandler);
}
$(document).ready(onReadyHandler);
When you do something like .click(function(){...}), here function is called as a callback. You have to send a function as a callback. Not necessary to be anonymous.
I'm stuck with my modal popup plugin since a week.
I'll try to explain as much as i can but first, here is the jsfiddle: http://jsfiddle.net/hideo/yth37hhf/27/
I know the code contains some other functions but they are useful for my plugin.
So, my issue is that the function "triggerLinkAction" contains an addEventListener which is not fired.
(function() {
Window.prototype.triggerLinkAction = function(){
var triggeredLink = document.getElementById("triggeredOtherAction");
var inputTarget = document.getElementById("inputText");
console.log('triggeredLink',triggeredLink);
triggeredLink.addEventListener("click", function (e) {
alert('If this pops out, I will be very happy!!!');
e.preventDefault();
inputTarget.value = "This text should be on the input field...";
}, true);
}
})();
The targeted element is inside the modal, and this modal is displayed by clicking on the link "A small modal".
When the plugin calls ShowModal(), I trigger the TransitionEnd event to call a function
[.... code ...]
function ShowModal() {
vars.popupContainer.classList.add("show");
hsdk.PrefixedEvent(vars.popupOverlay, "TransitionEnd", function (e) {
executeFunctions();
});
}
[.... code ...]
The executeFunctions() will check which functions need to be called:
[.... code ...]
function executeFunctions() {
if (vars.opts && vars.opts.fn) {
var allFunctions = vars.opts.fn.split(',');
for (var i = 0; i < allFunctions.length; i++)
{
var functionName = allFunctions[i];
var functionToExecute = window[functionName];
if(typeof functionToExecute === 'function') {
functionToExecute();
}
}
}
}
[.... code ...]
There are some comments on the javascript part about the plugin, but feel free to ask if I can provide any other information.
PS: I don't care about IE for now ;-)
I've written a few events to handle opening and closing of a snap js drawer. This code below works, but I feel it could be written more efficiently. Any suggestions?
function openMobileMenu() {
event.preventDefault();
snapper.open('left');
$('#btn-menu').off('click', openMobileMenu);
$('#btn-menu').on('click', closeMobileMenu);
}
function closeMobileMenu() {
event.preventDefault();
snapper.close('left');
$('#btn-menu').on('click', openMobileMenu);
$('#btn-menu').off('click', closeMobileMenu);
}
$('#btn-menu').on('click', openMobileMenu);
Make your code modular and your concepts explicit.
You can start by creating a MobileMenu object which encapsulates the logic.
Note: The following code was not tested.
var MobileMenu = {
_snapper: null,
_$button: null,
_direction: 'left',
init: function (button, snapper, direction) {
this._$button = $(button);
this._snapper = snapper;
if (direction) this._direction = direction;
this._toggleSnapperVisibilityWhenButtonClicked();
},
_toggleSnapperVisibilityWhenbuttonClicked: function () {
this._$button.click($.proxy(this.toggle, this));
},
toggle: function () {
var snapperClosed = this._snapper.state().state == 'closed',
operation = snapperClosed? 'open' : 'closed';
this._snapper[operation](this._direction);
}
};
Then in your page you can just do the following to initialize your feature:
var mobileMenu = Object.create(MobileMenu).init('#btn-menu', snapper);
Modularizing your code will make it more maintainable and understandable in the long run, but also allow you to unit test it. You also gain a lot more flexibily because of the exposed API of your component which allows other code to interact with it.
E.g. you can now toggle the menu visibility with mobileMenu.toggle().
Use a variable to keep track of the state:
var menu_open = false;
$("#btn-menu").on('click', function(event) {
event.preventDefault();
if (menu_open) {
snapper.close('left');
} else {
snapper.open('left');
}
menu_open = !menu_open; // toggle variable
});
snap has a .state() method, which returns an object stuffed with properties, one of which is .state.
I think you want :
$('#btn-menu').on('click', function() {
if(snapper.state().state == "closed") {
snapper.open('left');
} else {
snapper.close('left');
}
});
Or, in one line :
$('#btn-menu').on('click', function() {
snapper[['close','open'][+(snapper.state().state == 'closed')]]('left');
});
Also, check How do I make a toggle button? in the documentation.
I am using the following (http://jsfiddle.net/mkmurray/drv5w/27/) code to allow me to override the .show() function of a DIV.
<script>
(function ($) {
var _oldShow = $.fn.show;
$.fn.show = function (/*speed, easing, callback*/) {
var argsArray = Array.prototype.slice.call(arguments),
duration = argsArray[0],
easing,
callback,
callbackArgIndex;
// jQuery recursively calls show sometimes; we shouldn't
// handle such situations. Pass it to original show method.
if (!this.selector) {
_oldShow.apply(this, argsArray);
return this;
}
if (argsArray.length === 2) {
if ($.isFunction(argsArray[1])) {
callback = argsArray[1];
callbackArgIndex = 1;
} else {
easing = argsArray[1];
}
} else if (argsArray.length === 3) {
easing = argsArray[1];
callback = argsArray[2];
callbackArgIndex = 2;
}
return $(this).each(function () {
var obj = $(this),
oldCallback = callback,
newCallback = function () {
if ($.isFunction(oldCallback)) {
oldCallback.apply(obj);
}
obj.trigger('afterShow');
};
if (callback) {
argsArray[callbackArgIndex] = newCallback;
} else {
argsArray.push(newCallback);
}
obj.trigger('beforeShow');
_oldShow.apply(obj, argsArray);
});
};
})(jQuery);
</script>
I have the following HTML code
<div id="divBeforeHiddenDiv">
foo
</div>
<div id="hiddenDiv" style="display:none">
bar
</div>
And then:
<script>
$('#hiddendiv').bind("beforeShow", function () {
alert("show event successfully overridden");
});
</script>
It works great when I call $('#hiddenDiv').show() but not if I call $('#divBeforeHiddenDiv').next().show() the hidden div containing 'bar' shows but the alert is not displayed.
So why?
UPDATE
This appears to be a jQuery issue as per Bergi's comment. If I use this JSFiddle on jQuery 1.7.1 it works but using jQuery 1.10.1 or any higher version it does not: JSFiddle. Is there a better solution than simply downgrading?
You need to bind the events to the proper elements.
From the example you've given, and what I've interpreted, this piece of code
$('#beforeShow').bind("beforeShow", function () {
alert("show event successfully overridden");
});
Should be
$('#hiddenDiv').bind("beforeShow", function () {
alert("show event successfully overridden");
});
As you want the events to be bound to the hidden div. (or as described in the question, the div right after "#divBeforeHiddenDiv"
You also should change this piece
$('divBeforeHiddenDiv').next().show()
to this
$('#divBeforeHiddenDiv').next().show()
divBeforeHiddenDiv is an ID and in the first code snippet there is no id in the jQuery object.
JSFiddle