I need to pass data between two autonomic user scripts - ideally without touching the unsafeWindow object - and I thought using custom events would be the way to go. I thought of something like this (let us disregard the MSIE model for the purpose of the example):
addEventListener("customEvent", function(e) {
alert(e.data);
});
var custom = document.createEvent("HTMLEvents");
custom.initEvent("customEvent", true, true);
custom.data = "Some data...";
dispatchEvent(custom);
This works nicely in the standard Javascript environment and within one user script, but when the event is fired by the user script and caught outside of it or inside another user script, the data property is undefined in Chromium. I suppose I could just save the passed data in the sessionStorage, but it is far from seamless. Any other elegant solutions? Perfection need and can be achieved, I can feel it.
Yes, you can use a MessageEvent or a CustomEvent.
Example usage:
//Listen for the event
window.addEventListener("MyEventType", function(evt) {
alert(evt.detail);
}, false);
//Dispatch an event
var evt = new CustomEvent("MyEventType", {detail: "Any Object Here"});
window.dispatchEvent(evt);
pass object with more details as attributes:
var event = new CustomEvent('build', { detail: { 'detail1': "something", detail2: "something else" }});
function eventHandler(e) {
log('detail1: ' + e.detail.detail1);
log('detail2: ' + e.detail.detail2);
}
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
new CustomEvent is not supported in IE https://caniuse.com/#search=CustomEvent
Here is a version which also works on IE9+:
//Listen for the event
window.addEventListener("MyEventType", function(evt) {
alert(evt.detail.test); //alerts "Any Object Here"
}, false);
//Dispatch an event
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent('MyEventType', false, false, { test: "Any Object Here" });
window.dispatchEvent(evt);
Related
I looked through many threads at SO, but could not find an answer that solves my problem. So, I define a CKEditor instance like so:
var editor = $('#test-editor');
editor.ckeditor(function() {}, {
customConfig: '../../assets/js/custom/ckeditor_config.js',
allowedContent: true
});
However I do not know how can I catch change event. This is what I tried:
var t = editor.ckeditor(function() {
this.on('change', function () {
console.log("test 1");
});
}, {
customConfig: '../../assets/js/custom/ckeditor_config.js',
allowedContent: true
});
editor.on('change', function() {
console.log("test 2");
});
t.on('change', function() {
console.log("test 3");
});
All these three attempts ended in failure. I should add, that I do not want to loop through all editors on a page, I just want to address one particular editor rendered at component with #test-editor. How can I do that?
The jQuery ckeditor() method returns a jQuery object, which exposes only 5 events of CKEditor in its event handling. In order to use other events, you need to use the CKEditor.editor object by accessing the editor property of the jQuery object.
So, you need to use something like this:
var myeditor = $('#test-editor').ckeditor({
customConfig: '../../assets/js/custom/ckeditor_config.js',
allowedContent: true
});
myeditor.editor.on('change', function(evt) {
console.log('change detected');
});
I have an event listener setup using jQuery like this:
$(document).on('my-custom-event', function(e, custom_id) {
console.log('the ID is: ' + custom_id);
});
It is easy to trigger this with jQuery.trigger, like this:
$(document).trigger('my-custom-event', '12345');
But I am trying to figure out how to trigger it with vanilla javascript, and also ensure that custom_id gets passed properly.
For example, this does not work. It triggers the event, but does not pass the custom_id argument:
var e = new CustomEvent('my-custom-event', 'asdf')
document.dispatchEvent(e)
How can I use plain javascript to trigger the event and also pass the custom_id argument?
According to MDN, detail can be used to pass data when initializing the event.
Here is an example:
// add listener
// let's be cool and add it to the document for this example
document.addEventListener('EVENT-NAME', function (e) {
// do something
// use e.detail for the data
});
// create event
var event = new CustomEvent('EVENT-NAME', {
detail: 'legit data'
});
// dispatch event
document.dispatchEvent(event);
I have also created a demo: http://jsfiddle.net/dirtyd77/02p2o7ut/1/
Hopefully this helps and let me know if you have any other questions!
EDIT:
Unfortunately, there is no way (that I know of) to do what you are asking, however, there is a workaround.
jQuery events have a property called originalEvent. You could check to see if that value exists in the event that custom_id does not. Here is how you could do this:
DEMO: http://jsfiddle.net/dirtyd77/02p2o7ut/2/
$(document).on('my-custom-event', function (e, custom_id) {
// if custom_id not defined, will check e.originalEvent.detail
custom_id = custom_id || e.originalEvent.detail;
console.log('the ID is: ' + custom_id);
});
// trigger jQuery event
$(document).trigger('my-custom-event', '12345');
$('#customEvent').click(function () {
// create event
var event = new CustomEvent('my-custom-event', { detail: '12345' });
// dispatch event
document.dispatchEvent(event);
});
Take a look at the following code:
this.dialog({
width: 500,
height: 260,
title: "Setup database",
content: $("<form>").append(table),
buttons: {
submit: function(_alert, dialog) {
dialog.find("form").each(function() {
var arr = $(this).serializeArray();
var data = {
mysql: true
};
var empty = false;
$(this).find("input").removeClass("error");
for (var k in arr) {
if ($.trim(arr[k].value) !== "") {
data[arr[k].name] = arr[k].value;
} else {
empty = true;
$(this).find("input[name='" + arr[k].name + "']").each(function() {
$(this).addClass("error");
});
break;
}
}
if (!empty) {
self.ajax({
url: url,
data: data
}, function(result) {
callback(result);
}, function() {
self.mysql(url, callback, _db_name, _db_user, _db_pass, is_dialog);
});
}
_alert.remove();
if($.isFunction(callback_submit)) {
callback_submit();
}
});
}
}
});
There are two parameters passed into the anonymous function that is supposed to trigger when the button "submit" is clicked. But I have no idea where these parameters are supposed to come from. Can someone explain? Is this related to passing parameters to an anonymous function in Javascript in general?
I don't think you get any argument passed to you when a button event callback is fired on jquery-ui dialog box
http://jsfiddle.net/3d7QC/1577/
buttons: {
"I've read and understand this": function() {
console.log(arguments);
// look at your console
$(this).dialog("close");
}
Only argument you get passed through to you is the customary jQuery event object.
There should only be one parameter passed to submit, which is the event object of the button itself, when clicked. So the context set is the submit button, if you need to access the dialog and modify it, you can do so by accessing the event.target property.
this.dialog({
buttons: {
submit: function(event) {
$(event).dialog('close'); //is the same as...
$(this).dialog('close');
}
});
The first argument _alert is the JS event object that is passed to every event handler in JavaScript. This is not specific to jQuery. javascript.info explains this as follows:
W3C way
Browsers which follow W3C standards always pass the event object as
the first argument for the handler.
For instance:
element.onclick = function(event) {
// process data from event
}
In the jQueryUI API reference they confirm that i
Specifies which buttons should be displayed on the dialog. The context
of the callback is the dialog element; if you need access to the
button, it is available as the target of the event object.
I illustrated this in a fiddle. Not sure what the second argument (dialog in your case) does, though. It's not passed in my example code.
Getting a weird error for .stopPropagation() in IE
My code is as follows:
$(document).ready(function(){
var options = {
$this: "",
$menuItems: $(".mainMenu > li"),
$blueBar: $(".blueBar"),
$submenuBg: $("#submenuBg"),
$sortOptions: $(".sortOptions"),
$submenu: $(".submenu"),
submenuClass: ".submenu",
blueBarClass: ".blueBar",
selectedClass: "selected",
sortOptionsClass: ".sortOptions",
subSubmenu: "ul",
subSubmenuClass: "sub-submenu"
};
$sortBy.toggle(function(){
options.$this = $(this);
ddlShow(event, options);
},
function(){
options.$this = $(this);
ddlHide(options);
}
);
});
var ddlShow = function(event, options){
event.stopPropagation();
options.$this.children(options.sortOptionsClass).show();
}
var ddlHide = function(options){
options.$this.children(options.sortOptionsClass).hide();
}
Getting the following error:
object doesn't support property or method 'stoppropagation'
Code works fine in Chrome and Firefox.
How do I solve this?
Note: The same code works fine without the object options.
in IE we do not have stopPropogation method available in javascript on event object. If you will search in google you will find different implementation of event object in ie and webkit based browsers. So in order to correct that jQuery has given a single interface for handling it so you should use jQuery way of doing events to stop getting this errors.
You can read this article to get more clarification http://www.quirksmode.org/js/introevents.html
replace
e.stopPropagation(); with
if (e.stopPropagation) e.stopPropagation(); else e.cancelBubble = true; worked for me
Thanks
Have your toggle handlers accept the event parameter from jQuery:
$sortBy.toggle(function(event){ // ADDED PARAMETER
options.$this = $(this);
ddlShow(event, options);
},
If you do not do this, then when calling ddlShow the argument event resolves to window.event, which is an object that has not been "normalized" by jQuery for cross-browser consistency.
Here:
$sortBy.toggle(function(){ <-- you must get the event object from jquery.
options.$this = $(this);
ddlShow(event, options);
},
function(){
options.$this = $(this);
ddlHide(options);
}
);
Then:
$sortBy.toggle(function(event){ ... ddlShow(event, options); }...
JQuery by default passes the event object, you just have to declare it in the function arguments to use it within the function.
$sortBy.toggle(function(event){
// Do your stuff here
})
Also, It's not advisable to use event as argument name.
event refers to the global event object. Define something like e
function(e, options){
e.stopPropagation();
//do stuff here
}
I need to pass data between two autonomic user scripts - ideally without touching the unsafeWindow object - and I thought using custom events would be the way to go. I thought of something like this (let us disregard the MSIE model for the purpose of the example):
addEventListener("customEvent", function(e) {
alert(e.data);
});
var custom = document.createEvent("HTMLEvents");
custom.initEvent("customEvent", true, true);
custom.data = "Some data...";
dispatchEvent(custom);
This works nicely in the standard Javascript environment and within one user script, but when the event is fired by the user script and caught outside of it or inside another user script, the data property is undefined in Chromium. I suppose I could just save the passed data in the sessionStorage, but it is far from seamless. Any other elegant solutions? Perfection need and can be achieved, I can feel it.
Yes, you can use a MessageEvent or a CustomEvent.
Example usage:
//Listen for the event
window.addEventListener("MyEventType", function(evt) {
alert(evt.detail);
}, false);
//Dispatch an event
var evt = new CustomEvent("MyEventType", {detail: "Any Object Here"});
window.dispatchEvent(evt);
pass object with more details as attributes:
var event = new CustomEvent('build', { detail: { 'detail1': "something", detail2: "something else" }});
function eventHandler(e) {
log('detail1: ' + e.detail.detail1);
log('detail2: ' + e.detail.detail2);
}
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
new CustomEvent is not supported in IE https://caniuse.com/#search=CustomEvent
Here is a version which also works on IE9+:
//Listen for the event
window.addEventListener("MyEventType", function(evt) {
alert(evt.detail.test); //alerts "Any Object Here"
}, false);
//Dispatch an event
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent('MyEventType', false, false, { test: "Any Object Here" });
window.dispatchEvent(evt);