I have written the following script that should run a GET request to a specific URL when a set of checkboxes are ticked on and off. It works perfectly locally but in Production, I get a 404 response.
Any idea why and how to fix it?
/**
* Remove all child nodes from an element
* #param {Object} element The element to empty
*/
function empty (element) {
var children = Array.prototype.slice.call(element.childNodes);
children.forEach(function (child) {
element.removeChild(child);
});
}
function toggleItem(toggler, itemType, itemUrl, itemState, itemSource) {
let outputDiv = toggler.parentNode.querySelector('.theme-park-item-toggler-output');
empty(outputDiv);
let xhr = new XMLHttpRequest();
xhr.open('GET', itemUrl);
xhr.send(null);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) { // 4 means "Done"
if (xhr.status === 204) { // 204 means processed successfully with no content returned
console.log('success');
if (itemState == true) {
let img = document.createElement('img');
img.src = itemSource;
outputDiv.appendChild(img);
}
} else {
console.log('Failure to toggle');
toggler.toggleAttribute('checked');
}
}
};
}
document.addEventListener("turbo:load", function() {
document.querySelectorAll('.theme-park-item-toggler').forEach(function(the_toggler) {
the_toggler.addEventListener('change', function(e) {
toggleItem(the_toggler, the_toggler.dataset.type, the_toggler.dataset.url, e.target.checked, the_toggler.dataset.source);
});
});
});
Related
I seem to get the following error: this.getPageHTML is not a function when executing my Modal class.
constructor(trigger) {
this.trigger = trigger;
}
/**
* Show Modal
* #param {Element} trigger The element that is triggering the Modal.
*/
showModal(trigger = this.trigger) {
switch (trigger.dataset.modaltype) {
case "media":
this.getPageHTML(trigger.dataset.url, (response) => {
const htmlContent = response.getElementById("content");
const modalContent = document
.getElementById("modal")
.querySelector(".modal-window__content");
// Inject response into Modal content
modalContent.insertAdjacentHTML("beforeend", htmlContent.innerHTML);
});
break;
default:
break;
}
}
getPageHTML(url, callback) {
if (!window.XMLHttpRequest) return;
const xhr = new XMLHttpRequest();
// Get the HTML
xhr.open("GET", url);
xhr.responseType = "document";
xhr.onloadstart = this.requestStarted;
xhr.onprogress = this.updateRequestProgress;
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
xhr.onload = function () {
if (callback && typeof callback === "function") {
callback(this.responseXML);
}
};
}
};
xhr.send();
}
Not sure why exactly my getPageHTML function is "not a function"?
In my main js file I call the class like this:
modalTriggers.forEach((trigger) => {
trigger.addEventListener("click", (e) => {
let modal = new Modal(trigger);
modal.showModal();
e.preventDefault();
});
});
Could be something super obvious I'm missing here. I have tried assigning the "this.getPageHTML" to an anonomous function like "this.getPageHTML = function(trigger.dataset.url, response) {...}" but it seems to loose what "trigger" is.
I am new to JavaScript and I want to use send_request function twice, but with different behaviour. Element with name button1 should show response on the element, whereas button2 not.
function send_request(url) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.send('data=test');
xhr.onload = function () {document.getElementById('reply').innerHTML = xhr.responseText;};
}
document.getElementById('button1').addEventListener('click', function() { send_request("/data.php"); });
document.getElementById('button2').addEventListener('click', function() { send_request("/clear_data.php"); });
Is it possible?
There are a number of ways to accomplish this, but if we just start with your basic requirement, you could have send_request simply take an argument that determines if the element should show the response.
function send_request(url, showResponse) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.send('data=test');
xhr.onload = function () {
// If showResponse is true, log the response. If not, don't
showResponse ? document.getElementById('reply').innerHTML = xhr.responseText : null;
};
}
document.getElementById('button1').addEventListener('click', function() {
// Call the function and indicate that the response should be shown
send_request("/data.php", true);
});
document.getElementById('bitton2').addEventListener('click', function() {
// Call the function and indicate that the response should not be shown
send_request("/clear_data.php", false);
});
You could give send_request another parameter, a function that's called with the responseText, so you could pass one function that assigns to reply, and another function that does whatever you want instead:
function send_request(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.send('data=test');
xhr.onload = () => callback(xhr.responseText);
}
document.getElementById('button1').addEventListener('click', function() {
send_request("/data.php", (responseText) => {
document.getElementById('reply').innerHTML = responseText;
});
});
document.getElementById('bitton2').addEventListener('click', function() {
send_request("/clear_data.php", (responseText) => {
console.log('bitton 2 response: ' + responseText);
});
});
im trying to change an AJAX Code to add a small change effect so users can see that something happend on screen, cause the change of the content is hidden and its hard to notice that only some numbers have changed
function changeBox(post) {
if (http != null) {
http.open("POST", 'ajaxchangebox.php', true);
http.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
http.onreadystatechange = function() {
if (!http) {
return;
}
if (http.readyState == 4) {
document.getElementById("box").innerHTML = http.responseText;;
}
}
http.send(post);
}
}
I am not familiar with Javascript/AJAX. The kind of effect itself is not important. it should be something flashing, short change of colour or something like that.
Thanks for your help
Christian
Maybe this can help: Animate.css
usage:
document.getElementById("box").classList.add('bounce animated')
You need to add a listener to catch animation end event:
var onDone = (function(){
var elm = document.getElementById('box');
var animateEndName = function () {
var i,
el = document.createElement('div'),
mapping = {
'animation': 'animationend',
'OAnimation': 'oanimationend',
'MozAnimation': 'animationend',
'WebkitAnimation': 'webkitAnimationEnd'
}
for (i in mapping) {
if (el.style[i] !== undefined) {
return mapping[i];
}
}
}();
elm.addEventListener(animateEndName, function(){
elm.classList.remove('flash', 'animated');
});
return function(result){
elm.innerHTML = result;
elm.classList.add('flash', 'animated');
}
})();
I'm working on an addon to a forum and I get this error:
Error: Component returned failure code: 0x8007000e (NS_ERROR_OUT_OF_MEMORY) [nsIXPCComponents_Utils.evalInSandbox]
I read that the error means that the script goes into infinite loop until it fills the sandbox.
apparently the js file that leads to this error is script-compiler.js
this is the script:
var ddplus_gmCompiler={
// getUrlContents adapted from Greasemonkey Compiler
// http://www.letitblog.com/code/python/greasemonkey.py.txt
// used under GPL permission
//
// most everything else below based heavily off of Greasemonkey
// http://greasemonkey.mozdev.org/
// used under GPL permission
getUrlContents: function(aUrl){
var ioService=Components.classes["#mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var scriptableStream=Components
.classes["#mozilla.org/scriptableinputstream;1"]
.getService(Components.interfaces.nsIScriptableInputStream);
var channel=ioService.newChannel(aUrl, null, null);
var input=channel.open();
scriptableStream.init(input);
var str=scriptableStream.read(input.available());
scriptableStream.close();
input.close();
return str;
},
isGreasemonkeyable: function(url) {
var scheme=Components.classes["#mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService)
.extractScheme(url);
return (
(scheme == "http" || scheme == "https" || scheme == "file") &&
!/hiddenWindow\.html$/.test(url)
);
},
contentLoad: function(e) {
var unsafeWin=e.target.defaultView;
if (unsafeWin.wrappedJSObject) unsafeWin=unsafeWin.wrappedJSObject;
var unsafeLoc=new XPCNativeWrapper(unsafeWin, "location").location;
var href=new XPCNativeWrapper(unsafeLoc, "href").href;
if (
ddplus_gmCompiler.isGreasemonkeyable(href)
&& ( /http:\/\/ddunlimited\.net/.test(href) )
&& true
) {
var script=ddplus_gmCompiler.getUrlContents(
'chrome://ddplus/content/ddplus.js'
);
ddplus_gmCompiler.injectScript(script, href, unsafeWin);
}
},
injectScript: function(script, url, unsafeContentWin) {
var sandbox, script, logger, storage, xmlhttpRequester;
var safeWin=new XPCNativeWrapper(unsafeContentWin);
sandbox=new Components.utils.Sandbox(safeWin);
var storage=new ddplus_ScriptStorage();
xmlhttpRequester=new ddplus_xmlhttpRequester(
unsafeContentWin, window//appSvc.hiddenDOMWindow
);
sandbox.window=safeWin;
sandbox.document=sandbox.window.document;
sandbox.unsafeWindow=unsafeContentWin;
// patch missing properties on xpcnw
sandbox.XPathResult=Components.interfaces.nsIDOMXPathResult;
// add our own APIs
sandbox.GM_addStyle=function(css) { ddplus_gmCompiler.addStyle(sandbox.document, css) };
sandbox.GM_setValue=ddplus_gmCompiler.hitch(storage, "setValue");
sandbox.GM_getValue=ddplus_gmCompiler.hitch(storage, "getValue");
// kick : aggiunta la funzione
sandbox.GM_remove=ddplus_gmCompiler.hitch(storage, "remove");
sandbox.GM_openInTab=ddplus_gmCompiler.hitch(this, "openInTab", unsafeContentWin);
sandbox.GM_xmlhttpRequest=ddplus_gmCompiler.hitch(
xmlhttpRequester, "contentStartRequest"
);
//unsupported
sandbox.GM_registerMenuCommand=function(){};
sandbox.GM_log=function(){};
sandbox.GM_getResourceURL=function(){};
sandbox.GM_getResourceText=function(){};
sandbox.__proto__=sandbox.window;
try {
this.evalInSandbox(
"(function(){"+script+"})()",
url,
sandbox);
} catch (e) {
var e2=new Error(typeof e=="string" ? e : e.message);
e2.fileName=script.filename;
e2.lineNumber=0;
//GM_logError(e2);
alert(e2);
}
},
evalInSandbox: function(code, codebase, sandbox) {
if (Components.utils && Components.utils.Sandbox) {
// DP beta+
Components.utils.evalInSandbox(code, sandbox);
} else if (Components.utils && Components.utils.evalInSandbox) {
// DP alphas
Components.utils.evalInSandbox(code, codebase, sandbox);
} else if (Sandbox) {
// 1.0.x
evalInSandbox(code, sandbox, codebase);
} else {
throw new Error("Could not create sandbox.");
}
},
openInTab: function(unsafeContentWin, url) {
var tabBrowser = getBrowser(), browser, isMyWindow = false;
for (var i = 0; browser = tabBrowser.browsers[i]; i++)
if (browser.contentWindow == unsafeContentWin) {
isMyWindow = true;
break;
}
if (!isMyWindow) return;
var loadInBackground, sendReferrer, referrer = null;
loadInBackground = tabBrowser.mPrefs.getBoolPref("browser.tabs.loadInBackground");
sendReferrer = tabBrowser.mPrefs.getIntPref("network.http.sendRefererHeader");
if (sendReferrer) {
var ios = Components.classes["#mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
referrer = ios.newURI(content.document.location.href, null, null);
}
tabBrowser.loadOneTab(url, referrer, null, null, loadInBackground);
},
hitch: function(obj, meth) {
var unsafeTop = new XPCNativeWrapper(unsafeContentWin, "top").top;
for (var i = 0; i < this.browserWindows.length; i++) {
this.browserWindows[i].openInTab(unsafeTop, url);
}
},
apiLeakCheck: function(allowedCaller) {
var stack=Components.stack;
var leaked=false;
do {
if (2==stack.language) {
if ('chrome'!=stack.filename.substr(0, 6) &&
allowedCaller!=stack.filename
) {
leaked=true;
break;
}
}
stack=stack.caller;
} while (stack);
return leaked;
},
hitch: function(obj, meth) {
if (!obj[meth]) {
throw "method '" + meth + "' does not exist on object '" + obj + "'";
}
var hitchCaller=Components.stack.caller.filename;
var staticArgs = Array.prototype.splice.call(arguments, 2, arguments.length);
return function() {
if (ddplus_gmCompiler.apiLeakCheck(hitchCaller)) {
return;
}
// make a copy of staticArgs (don't modify it because it gets reused for
// every invocation).
var args = staticArgs.concat();
// add all the new arguments
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
// invoke the original function with the correct this obj and the combined
// list of static and dynamic arguments.
return obj[meth].apply(obj, args);
};
},
addStyle:function(doc, css) {
var head, style;
head = doc.getElementsByTagName('head')[0];
if (!head) { return; }
style = doc.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
},
onLoad: function() {
var appcontent=window.document.getElementById("appcontent");
if (appcontent && !appcontent.greased_ddplus_gmCompiler) {
appcontent.greased_ddplus_gmCompiler=true;
appcontent.addEventListener("DOMContentLoaded", ddplus_gmCompiler.contentLoad, false);
}
},
onUnLoad: function() {
//remove now unnecessary listeners
window.removeEventListener('load', ddplus_gmCompiler.onLoad, false);
window.removeEventListener('unload', ddplus_gmCompiler.onUnLoad, false);
window.document.getElementById("appcontent")
.removeEventListener("DOMContentLoaded", ddplus_gmCompiler.contentLoad, false);
},
}; //object ddplus_gmCompiler
function ddplus_ScriptStorage() {
this.prefMan=new ddplus_PrefManager();
}
ddplus_ScriptStorage.prototype.setValue = function(name, val) {
this.prefMan.setValue(name, val);
}
ddplus_ScriptStorage.prototype.getValue = function(name, defVal) {
return this.prefMan.getValue(name, defVal);
}
ddplus_ScriptStorage.prototype.remove = function(name) {
return this.prefMan.remove(name);
}
window.addEventListener('load', ddplus_gmCompiler.onLoad, false);
window.addEventListener('unload', ddplus_gmCompiler.onUnLoad, false);
The user script is massive and available in this gist.
To be able to see the error:
install the addon
go to the message board at http://ddunlimited.net/
open any thread and open click the reply link
The message will appear as soon as the reply page loads.
in practice is a tool created specifically for a forum ... with the functions targeted to simplify the daily actions of the moderator. Now the forum has changed domain and tried to make it compatible with the new forum. I'm editing the js file with a simple text editor. ettengo the error when I edit the script that I posted above. if you do not touch this script ... some functions disappear and are no longer present.
someone can help me? thank you very much: D
OK, reproducible after all. The error in this case has a bogus message, as this isn't actually an OOM condition, but evalInSandbox() receiving a notification from the JS engine that the script was aborted (due to it being unresponsive) and evalInSandbox() not being able to tell the difference.
The reason is an infinite loop in your code at line 425 (cont.):
var max = textArea.parentNode.parentNode.clientHeight;
while (max == textArea.parentNode.parentNode.clientHeight)
textArea.rows++;
This loop whill never abort as the condition will never get false.
I have the following functions:
$(function() { //add new language
var lg_select = $('#add_language');
var table = lg_select.parent();
var table_head = $('form[name=languageData] tr').has('th')
$('.cv_addLang').click(function(e) {
e.preventDefault();
if(table_head.is(':hidden')) {
$('.nolangauge').hide();
table_head.show();
}
var new_lang = lg_select.clone();
new_lang.find('select[disabled=disabled]').removeAttr('disabled');
new_lang.find('select[name=new_language]').attr('name', 'language[]');
new_lang.find('select[name=new_level]').attr('name', 'language_level[]');
new_lang.appendTo(table).show();
})
})
function getXMLHttpRequestObject() { //ajax
var ajax = false;
if(window.XMLHttpRequest) {
ajax = new XMLHttpRequest();
} else if(window.ActiveXObject) {
try {
ajax = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
ajax = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
}
}
}
return ajax;
}
$(function() { //ajax
var ajax = getXMLHttpRequestObject();
if(ajax) {
$('div').delegate(".but_cv_w", "click", function(e){
e.preventDefault();
var div_content = $(this).parent().parent();
if(div_content) {
var x=$(div_content).attr('id');
//alert(x);
//alert(div_content);
var path = $(this).attr('href');
//alert(path);
ajax.open('get', path + '&ajax=true');
ajax.onreadystatechange=function() {
if(ajax.readyState == 4) {
if((ajax.status == 200) || (ajax.status == 304)) {
$(div_content).html(ajax.responseText);
} else {
$(this).click;
}
}
}
ajax.send(null);
return false;
}
})
}
})
The problem is that both new language and ajax are working fine but separated. If I delete the ajax function then new language function is working but if I keep the ajax function and make an ajax request then the other function (new language) isn't working anymore. It seams that after an ajax request the new language function dosen't work the seam as befor the ajax request.
The new language function is supposed to add new inputs for languages, the "cv_addLang" is the calss of an button which appears on the page after an normal server request or after a ajax request?
Hope someone could help me with this ??
Thanks for any help!
The Problem lies on the add new language function. Instead of an click event it is necesary to use delegate event and so the function should look like this in order for it to work.
$(function () { //add new language
$("body").delegate('.cv_addLang','click',function(e) {
e.preventDefault();
var lg_select = $('#add_language');
var table = lg_select.parent();
var table_head = $('form[name=languageData] tr').has('th');
if(table_head.is(':hidden')) {
$('.nolangauge').hide();
table_head.show();
}
var new_lang = lg_select.clone();
new_lang.find('select[disabled=disabled]').removeAttr('disabled');
new_lang.find('select[name=new_language]').attr('name', 'language[]');
new_lang.find('select[name=new_level]').attr('name', 'language_level[]');
new_lang.appendTo(table).show();
});
})