ajax:success callback doesn't fire after conversion from Coffeescript to ES6 - javascript

I have some ajax Form on my page.
I create a class to manage the behaviour of the buttons, and I have to change the class after the ajax success.
export class Following {
constructor(element) {
element = $(element);
this.follow = element.find('.follow');
this.unfollow = element.find('.following');
this.followForm = this.follow.parents('form');
this.unfollowForm = this.unfollow.parents('form');
this.bindClicks();
}
bindClicks() {
this.followForm.on('ajax:error', this.trySignIn);
this.followForm.on('ajax:success', event => {
console.log('follow success')
});
this.unfollowForm.on('ajax:success', event => {
console.log('unfollow success')
});
}
static init() {
$('.follow-unfollow-buttons').each((i, el) => new Following($(el)));
}
};
When I submit the form, the ajax call is a success, but I cannot intercept the callback. Why?

Solved, I'm using jquery-ujs instead of rails-ujs

Related

Trigger click event of dynamic loaded content from ajax call

Unable to trigger click event for an dynamically loaded content from ajax call. Tried to use trigger method but guess I am missing something here.
$("#call-setup").on("click", function () {
var $this = $("#settings")
var url = $this.data("link")
loadwifinetworks(url);
//$("#connectivity").trigger("click")
});
async function loadwifinetworks(url) {
await new Promise((resolve) => {
$.get(url, function (context) {
$("#contentArea").html(context);
resolve("success")
});
});
//$('body').find('#connectivity').trigger('click');
// $('#contentArea').find('#connectivity').trigger("click")
}

Angular 2+ detect closing window

i have troubles detecting a closing window after the build is done.
const newWindow = window.open(url, '_blank', options);
newWindow.onbeforeunload = () => null;
newWindow.addEventListener('beforeunload', (evt: BeforeUnloadEvent) =>
{
console.log(evt)
}
);
it works great until i do the build, there the beforeunload event does not get triggered. i also tried placing a host listener in the new window's component:
#HostListener('window:beforeunload', [ '$event' ])
beforeUnloadHander(event: BeforeUnloadEvent): void {
debugger;
}
but the same problem here. after the build is done, we don't arrive at the debugger anymore
anybody any idea what i am doing wrong? thanks for your help!
Edit Workaround
const heartBeatNewWindow = setInterval(() => {
if (newWindow.closed) {
this.canvasSettings.displayInNewWindow = false;
clearTimeout(heartBeatNewWindow);
}
}, 1500);
I had to do something similar and my approach was the following:
I created a generic catch from close event windows in the constructor of my service, them call method what handle this event. Inside this method I validate the origin of this event is the correct to execute the logic I needed. Look this example:
Inside the constructor:
if(window.addEventListener){
window.addEventListener("message", this.authService.handleMessage.bind(this), false);
}else{
(<any>window).attachEvent('onmessage', this.authService.handleMessage.bind(this));
}
And my method to handle that event:
handleMessage(event: Event) {
event.preventDefault();
const message = event as MessageEvent;
// Only trust messages from the below origin.
//
if ((message.origin !== environment.BASE_URL)) return;
const result = JSON.parse(message.data);
//Add your logic here
I Hope be helpfull.

Undo preventDefault() after API call

I am writing external script to check availability for e-commerce store. When "Add to basket" button is pressed, I'm calling my API and checking if product is available to order. However, I don't know how to undo preventDefault(). When condition is true, event under button should continue and product should be added to basket as without the script.
button.addEventListener('click', (event) => {
event.preventDefault();
fetch(`https://example.com/api.php?part=${partId}`)
.then(function (response) {
return response.json();
})
.then(function (jsonRes) {
console.log(JSON.stringify(jsonRes));
if (jsonRes.part.partFound == true) {
console.log('Found! Processing...');
// REMOVE preventDefault() and process
} else {
console.log('Not found! Aborting...', partId);
}
});
});
If your button is type="submit" change it totype="button"`. This
a) Won't submit the form
b) Means that you don't have to use preventDefault to prevent the form from submitting
That simply means you're left to decide how you want the data to be submitted, and you can either do that with another AJAX call to an API endpoint, or by submitting the whole form to the server - whichever is your setup.
// Grab the form and button, and add an event
// listener to the button
const form = document.querySelector('form');
const button = document.querySelector('button');
button.addEventListener('click', handleClick, false);
// Fake API call
function fakeAPI() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`API called!`)
}, 2000);
});
}
function handleClick() {
console.log('Clicked');
fakeAPI(2000).then(data => {
// If partfound submit the form data
// Either another fetch call to post the data,
// or `form.submit()` to post the whole form instead
});
}
<form>
<button type="button">
Click
</button>
</form>
you can try something like code below:
async function apiCall(onSuccess, onError) {
fetch(`https://example.com/api.php?part=${partId}`)
.then(function (response) {
return response.json();
})
.then(function (jsonRes) {
console.log(JSON.stringify(jsonRes));
if (jsonRes.part.partFound == true) {
console.log('Found! Processing...');
onSuccess(jsonRes);
} else {
console.log('Not found! Aborting...', partId);
onError();
}
});
}
button.addEventListener('click', (event) => {
// show loading or something
apiCall(function (response) {
// success
}, function () {
// error
});
});

HTML-based event listener for webcomponents/custom events (JS)

TL;DR; Is it possible to define an event listener in HTML (not JS) for a custom events?
Basing on this codepen, I'm trying to do the following:
<my-checkreport
onclick="myFunction()"
oncheck="myFunction1)"
check="myFunction()"
></my-checkreport>
where myFunction does some console.log stuff that I can see in the browser console. Native onlick works, of course, but neither oncheck nor check work, for the custom event defined below (source taken from above linked codepen):
customElements.define('my-checkbox', class extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({mode: 'open'});
this.checkEvent = new CustomEvent("check", {
bubbles: true,
cancelable: false,
});
shadowRoot.innerHTML = `
<label>
<input type="checkbox" id="my-checkbox"></input>
Dummy Enabled
</label>`;
shadowRoot.querySelector('#my-checkbox').addEventListener('click', (e) => {
console.log('checked', e.target.checked);
this.dispatchEvent(this.checkEvent);
});
}
});
Is it possible to attach event listeners for custom events in HTML?
This is the closest I can come to emulating the DOM declaration of an event handler. This code does everything, from what I can tell, that the DOM does for built in event handlers.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>On-Event Test</title>
<script>
function onCheckHandler(event) {
console.log('onCheckHandler: %O', event);
event.stopPropagation();
event.stopImmediatePropagation();
//event.preventDefault();
}
function eventListener(event) {
console.log('eventListener: %O', event);
}
(function() {
var template = `<div>Click to Check</div>`;
class MyEl extends HTMLElement {
constructor() {
super();
var rootEl = this.attachShadow({mode: 'open'});
rootEl.innerHTML = template;
rootEl.firstChild.addEventListener('click', () => {
var checkEvent = new CustomEvent("check", {bubbles:true,cancelable:true});
if (this.dispatchEvent(checkEvent)) {
// Do default operation here
console.log('Performing default operation');
}
});
this._onCheckFn = null;
}
static get observedAttributes() {
return ['oncheck'];
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (attrName === 'oncheck' && oldVal !== newVal) {
if (newVal === null) {
this.oncheck = null;
}
else {
this.oncheck = Function(`return function oncheck(event) {\n\t${newVal};\n};`)();
}
}
}
get oncheck() {
return this._onCheckFn;
}
set oncheck(handler) {
if (this._onCheckFn) {
this.removeEventListener('check', this._onCheckFn);
this._onCheckFn = null;
}
if (typeof handler === 'function') {
this._onCheckFn = handler;
this.addEventListener('check', this._onCheckFn);
}
}
}
// Define our web component
customElements.define('my-el', MyEl);
})();
</script>
</head>
<body>
<my-el oncheck="onCheckHandler(event)"></my-el>
</body>
</html>
To get this to work you need two steps:
Step One:
The component code must support an attribute change.
When the attribute is set to a string (The function to call) then the code creates a temporary function that attempts to call the function provided as the attribute value. That function is then passed on to step two.
When the attribute is set to anything else or the attribute is removed then the code passes a null on to step two.
Step Two:
The component code must support the oncheck property.
Whenever this property is changed it needs to remove any previously defined event handler for this property by calling removeEventListener.
If the new value of the property is a function then is calls addEventListener with that function as the handler.
This was fun to figure out. At first I thought that the DOM based oncheck handler would always be first. But by testing onclick and addEventHandler('click') I discovered that the event handlers are added in the order received. If onclick is provided in the DOM than that event listener is added first. If you then call removeAttribute('onclick') and then setAttribute('onclick', 'handler(event)') then that event handler is moved to the end of the list.
So this code replicates exactly what I same with the click event.
Without any JS code? No. But you could define a property in the constructor of your element to get the element attribute and eval it. For example,
constructor() {
// Other code.
const onCheckFunc = this.getAttribute('oncheck')
this.addEventListener('check', () => eval(onCheckFunc))
// Rest of your code.
}
EDIT: As mentioned by #Intervalia, you shouldn't inspect attributes of the element in constructor. You could do this in connectedCallback. But remember:
In general, work should be deferred to connectedCallback as much as possible—especially work involving fetching resources or rendering. However, note that connectedCallback can be called more than once, so any initialization work that is truly one-time will need a guard to prevent it from running twice.
In general, the constructor should be used to set up initial state and default values, and to set up event listeners and possibly a shadow root.

popstate HTML 5 event being fired multiple times

Hi i am using the following code to load a part of page dynamically using jquery
loadNextBackInPage_URL = null;
function callBackFunctionLoadNextBackInPage(data)
{
//alert(data);
$("#left").fadeTo(100,1);
var data = $(data).find( '#left' );
$("#left").html(data);
if(supports_history_api())
{
history.pushState(null, null, loadNextBackInPage_URL);
window.addEventListener("popstate", function(e) {
alert('s');
loadNextBackInPage(location.pathname);
});
}
else
{
}
}
function loadNextBackInPage(url,parm)
{
//alert(url);
loadNextBackInPage_URL = url;
$("#left").fadeTo(100,.2);
$.post(url,parm,callBackFunctionLoadNextBackInPage,'html');
}
The loading part and even changing the browser URL is working. but why is the PoP state function being fired multiple times?
I call loadNextBackInPage() originally through an onclick function.
I got it solved from here in codingforums
think you keep adding "popstate"
listeners over and over ...
Program logic:
Page loaded
onclick will execute loadNextBackInPage()
Start a $.post() Request and fire "callBackFunctionLoadNextBackInPage" on completion
pushState()
Register an event listener for "popstate"
When "popstate" fires, execute loadNextBackInPage() and return to step 2
So step 4 will be executed over and
over which will register new event
listeners. Every time "popstate" fires
all the event listeners will execute
Try to move the addEventListener
method call out of this loop
So from those i derived a workaround and also corrected location.pathname to location.href
The corrected code:
loadNextBackInPage_URL = null;
popEventListnerAdded = false;
function callBackFunctionLoadNextBackInPage(data)
{
//alert(data);
$("#left").fadeTo(100,1);
var data = $(data).find( '#left' );
$("#left").html(data);
if(supports_history_api())
{
history.pushState(null, null, loadNextBackInPage_URL);
if(!popEventListnerAdded) {
window.addEventListener("popstate", function(e) {
loadNextBackInPage(location.href);
});
popEventListnerAdded = true;
}
}
else
{
}
}
function loadNextBackInPage(url,parm)
{
//alert(url);
loadNextBackInPage_URL = url;
$("#left").fadeTo(100,.2);
$.post(url,parm,callBackFunctionLoadNextBackInPage,'html');
}

Categories