I am trying to make an existing php web application CSP compliant by doing away with 'unsafe-inline' in the 'script-src' directive
The code currently ( working but only due to unsafe-inline ):
// Currently - button in a php form
<button type="submit" class="btn-dark" name="button_clearUser"
onclick="return singleConfirm('Proceed ?')" >Clear Penalty</button>
// js function in an external javascript file
function singleConfirm( msg1 ) {
if (confirm(msg1)) {
return true;
} else {
return false;
}
}
To make the above fully CSP compliant, I attempted the following ...
// Amended - button in a php form - added class confirm
<button type="submit" class="btn-dark confirm" name="button_clearUser"
>Clear Penalty</button>
// Amended - added a eventListener in the external js file
// for class confirm
document.addEventListener('DOMContentReady', function () {
document.getElementsByClassName('confirm')
.addEventListener('click', return singleConfirm(msg1));
});
The above amendments are not working. And I dont see any error in the browser console. I suspect it a JS issue.
Pls advise.
................................ Updates Below ..............................
Update 3 ( the only issue left is that even when i click cancel, the form still submits. With onclick method, the 'return' keyword is used. Not sure how to implement 'return' concept here ) :::
Fixed ReferenceError: msg1 is not defined
function singleConfirm(msg1) {
if (confirm(msg1)) {
return true;
} else {
return false;
}
}
document.addEventListener('DOMContentLoaded', function () {
const elems = document.getElementsByClassName('confirm');
Array.prototype.forEach.call(elems, (elem) => {
elem.addEventListener('click', () => singleConfirm('Proceed ?'));
});
});
Update 2 :::
Used array for getElementsByClassName.
With the this update, I now have a modal window popping but only if i remove msg1 ( gives ReferenceError: msg1 is not defined )
document.addEventListener('DOMContentLoaded', function () {
const elems = document.getElementsByClassName('confirm');
Array.prototype.forEach.call(elems, (elem) => {
elem.addEventListener('click', () => singleConfirm(msg1));
});
});
Update 1 :::
Replaced DOMContentReady -> DOMContentLoaded
document.addEventListener('DOMContentLoaded', function () {
});
Finally got it to work as below...
function singleConfirm(msg1) {
if (confirm(msg1)) {
return true;
} else {
return false;
}
}
// Use class confirmProceed on the php/html form
document.addEventListener('DOMContentLoaded', function () {
const elems = document.getElementsByClassName('confirmProceed');
Array.prototype.forEach.call(elems, (elem) => {
elem.addEventListener('click', (event) => {
if ( !singleConfirm('Proceed with Action?') ){
event.preventDefault();
}
});
});
});
Related
window.onload = function () {
document.getElementById("lin").addEventListener("click", function func1(event) {
console.log('prevent defaul stopped')
event.preventDefault()
});
}
window.onload = function () {
document.getElementById("btn").addEventListener("click", function func2(event) {
console.log(' button prevent defaul stopped')
event.preventDefault()
});
}
Working on a Drupal 9 site and trying to add some custom JS code to a page.
Drupal.behaviors.syfyGlobalHideMenu = {
attach: function (context, settings) {
$('.nav-flyout', context).once('remove-modals', function () {
$(document).keyup(function (e) {
if (e.keyCode == 27) {
$('.nav-flyout', context).removeClass('js-flyout-active');
}
});
});
}
};
Wondering if there's a vanilla JS equivalent to the jQuery .once functionality above?
Currently Drupal attaches the event listener multiple times and I am trying to avoid that as I only want to attach the event listener once but have it remain attached and run every time the event is invoked.
let intervalID = null;
const search = document.querySelector(".call-us-table input#edit-search");
search.addEventListener("keydown", event => {
form.setAttribute("onsubmit", "return false");
clearInterval(intervalID);
});
search.addEventListener("keyup", event => {
intervalID = setInterval(submitForm, 2000);
});
Jquery once adds an html attribute to check if is the first time to run.
function vanillaOnce() {
if (!document.body.getAttribute('data-once')) {
document.body.setAttribute('data-once', 'true');
return true;
} else {
return false;
}
}
if (vanillaOnce) {
console.log('runs only once');
}
$('.slideArrow').toggle(function (event) {
//some code
}, function (event) {
//some code
});
This works fine for content which are loaded on page-load.But the same function does not work for content loaded with ajax.It just does not intercept the click.
What should I do?
In an other scenario,i faced a same problem(not for toggle,for click) and sorted it this way.I dont know what to do for toggle?
$('.common-parent').on('click','.target-of-click',function(){
//some code
})
The flag method :
var flag = false;
$(document).on('click', '.slideArrow', function(event) {
if (flag) {
// do one thing
}else{
// do another thing
}
flag = !flag;
});
the data method
$(document).on('click', '.slideArrow', function(event) {
if ( $(this).data('flag') ) {
// do one thing
}else{
// do another thing
}
$(this).data('flag', !$(this).data('flag'));
});
I recently have been upgrading the Phonegap to the latest version and now it forces me to follow the Chrome's Content Security Policy which in a way is good. But now I am forced to remove the all the onclick handlers in the HTML code and add them in the jquery handler some$(document).ready(function(evt){
$('#addRecordBtn').on('click', function(){
alert("Adding Record");
AddValueToDB();
});
$('#refreshBtn').on('click', function(){
alert("Refresh Records");
ListDBValues();
});
});
But as per what my app is scaled upto I feel that there will be too many of these handlers. Is there an example which shows maintenance of such handlers and a proper way or proper place of defining such handlers.
Here's an idea. You could make an object that stores all of the functions that also knows how to give up the function
var handlers = {
getHandler: function (str) {
return this[str];
},
'#addRecordBtn': function () {
alert("Adding Record");
AddValueToDB();
},
'#refreshBtn': function () {
alert("Refresh Records");
ListDBValues();
}
};
Then apply all of your handlers using this form.
$('#addRecordBtn').on('click', handlers.getHandler('#addRecordBtn'));
$('#refreshBtn').on('click', handlers.getHandler('#refreshBtn'));
Optimization Time if you want to get really fancy and you assign a unique ID to every button as convention
var handlers = {
defer: function () {
return function (){
handlers[$(this).attr('id')](arguments);
};
},
registerHandlers: function () {
for (var key in this) {
if (this.hasOwnProperty(key) && typeof(key) === "string") {
$('#' + key).on('click', this.defer());
}
}
},
'addRecordBtn': function () {
alert("Adding Record");
AddValueToDB();
},
'refreshBtn': function () {
alert("Refresh Records");
ListDBValues();
}
};
call it with
$('#addRecordBtn').on('click', handlers.defer());
$('#refreshBtn').on('click', handlers.defer());
or register everything automatically
handlers.registerHandlers();
Here is a fiddle of my solution
Do you look for something like this?
$('[data-clickhandler]').on('click', function(e) {
var $btn = $(e.currentTarget);
var handler = $btn.data('clickhandler');
alert('Refresh ' + handler);
window[handler] && window[handler](e);
e.preventDefault();
});
Now your elements can specify their clickhandler like so:
<a data-clickhandler="AddValueToDB" href="">...</a>
Or so:
<span data-clickhandler="ListDBValues">...</span>
I'm still a little new to jQuery events.
I'm trying to write jQuery a wrapper/framework of the Asp.NET UpdatePanel that automatically tracks UpdatePanel async updates.
I want to be able to do something like
$("#myUpdatePanel").on("update", myFunc);
and have it run some handler with this as the updated UpdatePanel. I actually have this bit working.
I also want to be able run a function exactly once any time one or many UpdatePanels update.
$.updatePanel.on("update", myRunOnceFunc);
This is where I'm having issues.
I've defined my wrapper:
// wrap updatePanel reload functionality
$.updatePanel = (function () {
var prm;
var UpdatePanel = function () { };
UpdatePanel.prototype = { };
// initialize on $(document).ready()
$(function () {
prm = Sys.WebForms.PageRequestManager.getInstance();
if (prm) {
prm.add_pageLoaded(function (s, e) {
$.each(e.get_panelsUpdated(), function () {
// call panel-specific update event handlers
$(this).trigger($.Event("update"));
});
// triggered once no matter how many panels were updated
$(UpdatePanel).trigger($.Event("update"));
});
}
});
return $(UpdatePanel);
})();
Then in my code that uses $.updatePanel:
$(function() { $.updatePanel.on("update", myRunOnceFunc); });
What I'm finding is that myRunOnceFunc is being run during both $(this).trigger($.Event("update")); and $(UpdatePanel).trigger($.Event("update"));.
Any ideas why and how to fix it?
I figured out what was wrong.
Rather than return $(UpdatePanel);, I needed to call return $(new UpdatePanel());. Then I needed to replace $(UpdatePanel).trigger(...) with $.updatePanel.trigger(...). Code below:
// wrap updatePanel reload functionality
$.updatePanel = (function () {
var prm;
var UpdatePanel = function () { }
UpdatePanel.prototype = { };
$(function () {
prm = Sys.WebForms.PageRequestManager.getInstance();
if (prm) {
prm.add_pageLoaded(function (s, e) {
$.each(e.get_panelsUpdated(), function () {
$(this).trigger($.Event("update"));
});
// triggered once no matter how many panels were updated
$.updatePanel.trigger($.Event("update"));
});
}
});
return $(new UpdatePanel());
})();