Reputation: 1003
How do I create a custom javascript dot function that does the same thing as the following code in jQuery:
$(document).on("click touchstart", ".someClass", function() {
// code goes here
});
I'd like to declare it like this:
$(".someClass").onClick(function () {
// code goes here
});
It needs to:
work with dynamically created elements (hence jQuery .on() instead of .click())
work with computer clicks as well as touch taps
ideally, but not mandatorily, it would be written in pure javascript (no jQuery in the prototype itself, but can still be accessed through jQuery)
Object.prototype.onClick = function() {
$(document).on('click touchstart', this, arguments);
};
But I receive the following error in chrome console:
Uncaught TypeError: ((n.event.special[g.origType] || {}).handle || g.handler).apply is not a function
I think I'm declaring it incorrectly, and perhaps that this is also not the correct way to access events in javascript.
Upvotes: 1
Views: 817
Reputation: 4768
You are looking for Event Delegation this allows you too dynamically add elements and still have them respond to click.
const getDiv = (name) => {
if (Array.isArray(name) === false) name = [name];
let div2 = document.createElement('div');
name.forEach(n => div2.classList.add(n));
div2.innerText = `${name}`;
return div2;
};
const makeDivs = () => {
const div = document.querySelector('#main');
const {
dataset: {
count: x
}
} = div;
for (let i = 0; i < x; i++) {
div.appendChild(getDiv('div2'));
div.appendChild(getDiv('div3'));
div.appendChild(getDiv(['div2', 'div3']));
}
};
document.addEventListener('click', ({
target
}) => {
if (target.matches('.div2')) console.log('You clicked a DIV2');
if (target.matches('.div3')) console.log('You clicked a DIV3 !!')
if (target.matches('button')) makeDivs();
});
div {
border: 1px solid red;
margin: 5px;
}
<div id='main' data-count="10">
</div>
<button>Click Me!!!</button>
Wrapping this up into a custom function.
NOTE: I changed selector
param to be an array, this allows you to pass complex selectors e.g. div.myClass li:hover
const getDiv = (name) => {
if (Array.isArray(name) === false) name = [name];
let div2 = document.createElement('div');
name.forEach(n => div2.classList.add(n));
div2.innerText = `${name}`;
return div2;
};
const makeDivs = () => {
const div = document.querySelector('#main');
const {
dataset: {
count: x
}
} = div;
for (let i = 0; i < x; i++) {
div.appendChild(getDiv('div2'));
div.appendChild(getDiv('div3'));
div.appendChild(getDiv(['div2', 'div3']));
}
};
document.on = (eventType, selector, callback) => {
const events = eventType.split(' ');
const selectors = (Array.isArray(selector)) ? selector : [selector];
events.forEach(event => { document.addEventListener(event, (e) => {
if(selectors.some(s => e.target.matches(s))) callback(e);
});
});
};
// Convenience method.
document.onClick = (selector, callback) => document.on('click', selector, callback);
// Simple
document.on('click', 'button', () => makeDivs());
document.on('click', '.div2', ({target}) => console.log('You clicked a DIV2'));
// Multi Event
document.on('click touchstart', '.div3', () => console.log('You clicked a DIV3'));
// Multi selectors
document.on('click', ['.div2', '.div3'], ({target}) => console.log('You clicked. !!'));
document.onClick('div', ({target}) => console.log('A Click Event!!'));
div {
border: 1px solid red;
margin: 5px;
}
<div id='main' data-count="10">
</div>
<button>Click Me!!!</button>
Upvotes: 3
Reputation: 206228
So you want a .onClick
jQuery method
jQuery.fn.extend({
onClick: function(sel, cb) {
return this.on('touchstart click', sel, function(evt) {
evt.preventDefault();
if (cb && typeof cb === 'function') cb.apply(this, arguments);
})
}
});
$(document).onClick('.someClass', function(ev) {
console.log(ev.type)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="someClass">CLICK ME</p>
Or this simpler variant:
$.fn.onClick = function(sel, cb) {
return this.on('touchstart click', sel, cb);
};
$(document).onClick('.someClass', function(ev) {
ev.preventDefault();
console.log(ev.type)
});
Upvotes: 1