patternjavascriptMinor
Add classes onclick and then remove them with onfocus event
Viewed 0 times
withremoveclassesthenandonfocusthemeventaddonclick
Problem
Right now I'm mixing JS and jQuery. I would like to find one unique solution with JS only possibly.
How can I organize the code according to best code practices?
Another thing I need to add is a check at the beginning of the function. If the classes are there nothing should happen, if not there then add them just as below.
How can I organize the code according to best code practices?
Another thing I need to add is a check at the beginning of the function. If the classes are there nothing should happen, if not there then add them just as below.
function changeClass() {
document.getElementById("message").className += " dropzone-wrap";
document.getElementById("dragNdrop").className += " dropzone-content";
}
window.onload = function() {
document.getElementById("ToggleTxTDrop").addEventListener( 'click' , changeClass );
}
/* lets remove the previous classes when on focus */
$('#message').on('focus', function(){
$(this).removeClass('dropzone-wrap');
$(this).parent().removeClass('dropzone-content');
})Solution
Here's a step-by-step conversion from your code to the JS-only code of youmightnotneedjquery.com.
Your method here can only ever be used to add "dropzone-wrap" and "dropzone-content". Consider a different approach, where you provide the
Consider two such methods - one to add the class (from
Note that I'd remove the class before adding it, as that code does not protect against long repeated classname strings.
Anyway, let's continue with your code:
Using
For the function code itself, create a handler method that uses the
Now we have your classes being added on click; let's update the onfocus handler in the same fashion:
If the classes are there nothing should happen
To address that, the
The full converted code:
It is worth noting that you can use inline functions as handlers, too - and not define
function changeClass() {
document.getElementById("message").className += " dropzone-wrap";
document.getElementById("dragNdrop").className += " dropzone-content";
}Your method here can only ever be used to add "dropzone-wrap" and "dropzone-content". Consider a different approach, where you provide the
DOM Element and CSS Classes as parameters.Consider two such methods - one to add the class (from
$.addClass()), and one to remove it ($.removeClass()).// http://youmightnotneedjquery.com/#add_class
function addClass(el, className) {
if (el.classList)
el.classList.add(className);
else
el.className += ' ' + className;
}
// http://youmightnotneedjquery.com/#remove_class
function removeClass(el, className) {
if (el.classList)
el.classList.remove(className);
else
el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
}Note that I'd remove the class before adding it, as that code does not protect against long repeated classname strings.
Anyway, let's continue with your code:
window.onload = function() {
document.getElementById("ToggleTxTDrop").addEventListener( 'click' , changeClass );
}Using
onload works, but it isn't the right way to do it. With jQuery this should be $(window).on('load', function() { ... });... with native Javascript, it isn't much different (.addEventListener).For the function code itself, create a handler method that uses the
addClass() abstraction method to replace your old changeClass() functionality:function txtDropClicked(evt) {
addClass(document.getElementById('message'), 'dropzone-wrap');
addClass(document.getElementById('dragNdrop'), 'dropzone-content');
}
window.addEventListener('load', function() {
document.getElementById("ToggleTxTDrop").addEventListener( 'click' , txtDropClicked );
});Now we have your classes being added on click; let's update the onfocus handler in the same fashion:
/* lets remove the previous classes when on focus */
function removeClassesOnFocus(evt) {
// evt.target is the element that triggered the event. We bound to #message.
removeClass(evt.target, 'dropzone-wrap');
removeClass(evt.target.parentNode, 'dropzone-content');
}
// this bit really should wait for `window.load` too.
document.getElementById('message').addEventListener('focus', removeClassesOnFocus);If the classes are there nothing should happen
To address that, the
removeClassesOnFocus function could be reworked to look up the element if it isn't provided.function txtDropClicked(evt) {
removeClassesOnFocus(false);
addClass(document.getElementById('message'), 'dropzone-wrap');
addClass(document.getElementById('dragNdrop'), 'dropzone-content');
}
function removeClassesOnFocus(evt) {
// evt.target is the element that triggered the event. We bound to #message.
var message = (evt === false) ? document.getElementById('message') : evt.target;
removeClass(message, 'dropzone-wrap');
removeClass(message.parentNode, 'dropzone-content');
}The full converted code:
// http://youmightnotneedjquery.com/#add_class
function addClass(el, className) {
if (el.classList) { el.classList.add(className); }
else { el.className += ' ' + className; }
}
// http://youmightnotneedjquery.com/#remove_class
function removeClass(el, className) {
if (el.classList) { el.classList.remove(className); }
else { el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); }
}
// When the txtDrop toggle is clicked, add these classes to the message and drag/drop thing.
function txtDropClicked(evt) {
removeClassesOnFocus(false);
addClass(document.getElementById('message'), 'dropzone-wrap');
addClass(document.getElementById('dragNdrop'), 'dropzone-content');
}
// Removes the classes after the message receives focus.
function removeClassesOnFocus(evt) {
// evt.target is the element that triggered the event. We bound to #message.
var message = (evt === false) ? document.getElementById('message') : evt.target;
removeClass(message, 'dropzone-wrap');
removeClass(message.parentNode, 'dropzone-content');
}
// Attach the click handler to txtDrop toggle when the page loads.
window.addEventListener('load', function() {
document.getElementById("ToggleTxTDrop").addEventListener( 'click' , txtDropClicked );
document.getElementById('message').addEventListener('focus', removeClassesOnFocus);
});It is worth noting that you can use inline functions as handlers, too - and not define
txtDropClicked or removeClassesOnFocus. Either way, the point of each method is to perform a single task, and to do that in the most reusable manner possible.Code Snippets
function changeClass() {
document.getElementById("message").className += " dropzone-wrap";
document.getElementById("dragNdrop").className += " dropzone-content";
}// http://youmightnotneedjquery.com/#add_class
function addClass(el, className) {
if (el.classList)
el.classList.add(className);
else
el.className += ' ' + className;
}
// http://youmightnotneedjquery.com/#remove_class
function removeClass(el, className) {
if (el.classList)
el.classList.remove(className);
else
el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
}window.onload = function() {
document.getElementById("ToggleTxTDrop").addEventListener( 'click' , changeClass );
}function txtDropClicked(evt) {
addClass(document.getElementById('message'), 'dropzone-wrap');
addClass(document.getElementById('dragNdrop'), 'dropzone-content');
}
window.addEventListener('load', function() {
document.getElementById("ToggleTxTDrop").addEventListener( 'click' , txtDropClicked );
});/* lets remove the previous classes when on focus */
function removeClassesOnFocus(evt) {
// evt.target is the element that triggered the event. We bound to #message.
removeClass(evt.target, 'dropzone-wrap');
removeClass(evt.target.parentNode, 'dropzone-content');
}
// this bit really should wait for `window.load` too.
document.getElementById('message').addEventListener('focus', removeClassesOnFocus);Context
StackExchange Code Review Q#93466, answer score: 5
Revisions (0)
No revisions yet.