This question already has answers here:
How do I include a JavaScript file in another JavaScript file?
(70 answers)
Closed 2 years ago.
I am using the following function to make an XHR request and execute javascript from the response if possible:
function ajaxRequest(resultDiv, processing, action, paramName, param, paramName2, param2, parseJs) {
if (processing) {
document.getElementById(resultDiv).innerHTML = processing;
}
var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
var resp = this.responseText;
document.getElementById(resultDiv).innerHTML = resp;
if (parseJs) {
parseScript(resp);
}
}
}
if (paramName2) {
xmlhttp.open("GET", "/query?" + paramName + "=" + param + "&" + paramName2 + "=" + param2 + "&action=" + action, true);
} else {
xmlhttp.open("GET", "/query?" + paramName + "=" + param + "&action=" + action, true);
}
xmlhttp.send();
}
function parseScript(strcode) {
var scripts = new Array();
while (strcode.indexOf("<script") > -1 || strcode.indexOf("</script") > -1) {
var s = strcode.indexOf("<script");
var s_e = strcode.indexOf(">", s);
var e = strcode.indexOf("</script", s);
var e_e = strcode.indexOf(">", e);
scripts.push(strcode.substring(s_e + 1, e));
strcode = strcode.substring(0, s) + strcode.substring(e_e + 1);
}
for (var i = 0; i < scripts.length; i++) {
try {
eval(scripts[i]);
} catch (ex) {
alert("Error while executing");
}
}
}
But I got to know that eval function is somehow dangerous and very slow. So can you help me to find something alternative of eval and rewrite the code snippet to work same way it meant to be but with alternative of eval? Thanks in advance, and sorry for my bad English.
An alternative to eval() might be to inject the code into a <script> tag on your page, upon which it is then immediately executed.
In the example below, the code is provided to script.text. For a URL as in your question, use script.src instead.
const script = document.createElement('script');
script.text = 'console.log("foo");';
document.body.append(script);
// logs "foo"
Eval can be slow but is as dangerous as any other solution if you are running code that is not trusted or verified by yourself. If you do need another way to run this you can try dynamic script text insertion as described in the answer here
Related
I'm trying to post # sing to make some words turn to hashtags but the code doesn't work and it's via API using this code:
true == function()
{
var getMyItem = function (str)
{
if (sessionStorage.getItem(str) == null)
{
setMyItem(str, 0);
return 0;
}
return sessionStorage.getItem(str);
}
var setMyItem = function (key, value)
{
sessionStorage.setItem(key, value);
}
function bot(post)
{
const Http = new XMLHttpRequest();
var Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // Token
var ID= "xxxxxx";
var url= 'https://bot.xxx/api/'+Token+'/sendMessage?text='+post+'&chat_id='+ID;
Http.open("GET", url);
Http.send();
}
// you need to change the url variable contents for your own Telegram API or those of the same SN APIs..
So when it comes to call the post like with this code:
var myDate = new Date().toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1");
var post_n = "%23Hi. It's: " + myDate + "\n";
var post = encodeURI(post_n);
if (getMyItem(key + "htr") != "yes")
{
bot(post);
setMyItem((key + "htr"),"yes");
}
return true;
}
}()
, it doesnt support # sign in my browsers including Chrome an Firefox and nothing is sent actually.
So if it were for Telegram, the bot would look like this (and I donno if it works or not but I'm talking about another SN):
var url= 'https://api.telegram.org/'+Token+'...
Please tell me how to send # code. By the way, "%23" doesn't work.
So I want to use ajax request and I know how to use it.
But problem that i had that I want to pass parameters to request. So My first page had 4 parameter then I build url like this,
var url = "./ControllerServlet?PAGE_ID=BPCLA&ACTION=closeAssessment&SAVE_FLAG=true&closeReason="+closeReasonStr+"&closeCmt="+closeCmt;
but now parameter is increasing like now I have 20 more. So now building url like this going to be messy approach. Is there a better way to do this.
Here is my function where i am building URL in javascript function.
function closeAssessment() {
var closeReason = document.getElementById("SectionClousureReason");
var closeReasonStr = closeReason.options[closeReason.selectedIndex].value;
var closeCmt=document.getElementById("SectionCloseAssessmentCmt").value;
var url = "./ControllerServlet?PAGE_ID=BPCLA&ACTION=closeAssessment&SAVE_FLAG=true&closeReason="+closeReasonStr+"&closeCmt="+closeCmt;
ajaxRequest(url);
return;
}
edit:
As you ask here is my ajaxRequest function,
function ajaxRequest(url) {
strURL = url;
var xmlHttpRequest = false;
var self = this;
// Mozilla, Safari
if (window.XMLHttpRequest) {
self.xmlHttpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
self.xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
self.xmlHttpRequest.open("POST", strURL, true);
self.xmlHttpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
self.xmlHttpRequest.onreadystatechange = function() {
if (self.xmlHttpRequest.readyState == 4) {
if (self.xmlHttpRequest.status == 200) {
var htmlString = self.xmlHttpRequest.responseText;
var parser = new DOMParser();
var responseDoc = parser.parseFromString(htmlString, "text/html");
window.close();
} else {
ajaxFailedCount++;
// Try for 1 min (temp fix for racing condition)
if (ajaxFailedCount < 1200) {window.setTimeout(function() {ajaxRequest(url)}, 50);}
else {alert("Refresh failed!")};
}
}
}
self.xmlHttpRequest.send(null);
}
You could make an object with the key/value pairs being what you want added to the URL.
var closeReason = document.getElementById("SectionClousureReason");
var params = {
PAGE_ID: 'BPCLA',
ACTION: 'closeAssessment',
SAVE_FLAG: 'true',
closeReasonStr: closeReason.options[closeReason.selectedIndex].value,
closeCmt: document.getElementById("SectionCloseAssessmentCmt").value
};
Then add them to the URL via a loop.
var url = "./ControllerServlet?";
var urlParams = Object.keys(params).map(function(key){
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
}).join('&');
url += urlParams;
ajaxRequest(url);
Note: I added encodeURIComponent just to be safe.
EDIT: From your comment, it seems you want to submit a <form> but you want to use AJAX to do so. In that case, you can loop over the form elements and build the above params object.
var params = {
PAGE_ID: 'BPCLA',
ACTION: 'closeAssessment',
SAVE_FLAG: 'true'
};
var form = document.getElementById('yourForm'),
elem = form.elements;
for(var i = 0, len = elem.length; i < len; i++){
var x = elem[i];
params[x.name] = x.value;
}
Build up an object of your parameters and put them in the uri through a loop like this:
var values= {
page_id: 'BPCLA',
action: 'test'
},
uri_params = [],
uri = 'http://yoururl.com/file.php?';
for (var param in values) uri_params.push( encodeURIComponent( param ) + '=' + encodeURIComponent( values[ param ] ) );
uri = uri + uri_params.join( '&' );
console.log( uri );
Or consider using POST to transport your parameters, as many browsers have limitations on the query string.
Edit: you can also build yourself a function which traverses your form and builds up the values object for you so you don't have to do it manually.
Be aware however that anyone can inject custom url paramters simpy by appending form elements before submitting the form (by using the developer tools for example) so keep that in mind.
If you are using jQuery you can use .serializeArray() or have a look at this answer for a possible function you could use.
I have done several searches for this and found many examples for lazy-loading, but I can't find just the right example for what I'm trying to accomplish. Here's the down and dirty...
I have an object, call it Library:
(function() {
function Library() {
// some code in here
this.path = "/library";
}
function library() {
var l = new Library;
l.lang('en');
return l;
}
Library.prototype.lang = function(lang) {
lang = lang || 'en';
var s = document.createElement( "script" );
s.setAttribute("type", "text/javascript");
s.setAttribute("src", this.path + "/lang/" + lang + ".js");
document.getElementsByTagName( "head" )[0].appendChild( s );
}
})();
So, what I'm trying to do is lazy-load a "language" file to augment the Library object. The language file would like something like:
(function( Library ) {
Library.prototype._lang = {
header: "Welcome",
greet: "Hello",
exit: "Goodbye"
};
} ).bind( this );
The problem is (obviously), because of the way it's loaded, the new Library object is returned before it has a chance to be augmented. I have tried adding an event listener to the document appending the new script tag, but that won't let me "return" the library object. I'm having trouble finding the right way to defer the return of the library object.
I know about require.js. It's a great lib, but I don't want to use it for this project.
Thanks for helping!
You can load the file using a synchronous XMLHTTPRequest and eval:
(function() {
// ...
Library.prototype.lang = function(lang) {
lang = lang || 'en';
load(this.path + "/lang/" + lang + ".js");
};
function load(url) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.send();
if (xhr.status !== 200) {
console.log("Failed to load " + url + ": " + xhr.statusText);
} else {
eval(xhr.responseText)(Library);
}
}
})();
This is the code I wrote:
function responseAjax(element, url, loader, data) {
if(request.readyState == 4) {
if(request.status == 200) {
//The response has 2 main parts: the main page element and the javascript that have the text "???PHPTOSCRIPT???" in between
output = request.responseText.split('???PHPTOSCRIPT???');
if (element) document.getElementById(element).innerHTML = output[0];//put first part into element
if (output[1] != "") eval(output[1]); //execute script
//remember the last request
if (typeof(url) !== 'undefined') {
document.cookie = "requestedURL=" + escape(url);
document.cookie = "requestedElement=" + escape(element);
document.cookie = "requestedLoader=" + escape(loader);
document.cookie = "requestedData=" + escape(data);
};
};
};
};
function ajax(url, element, loader, data, remember, async) {
remember = (typeof(remember) === 'undefined') ? false : remember;//remember last request. Default: false
async = (typeof(async) === 'undefined') ? true : async;//handle request asynchronously if true. Default: true
if (loader) document.getElementById(element).innerHTML = loader;
try { request = new XMLHttpRequest(); /* e.g. Firefox */}
catch(err) {
try { request = new ActiveXObject("Msxml2.XMLHTTP"); /* some versions IE */}
catch(err) {
try { request = new ActiveXObject("Microsoft.XMLHTTP"); /* some versions IE */}
catch(err) { request = false;}
}
}
if (request) {
url += "?r=" + parseInt(Math.random()*999999999);//handle the cache problem
//put an array of data into string. Default: null array
data = data || [];
for (var i = 0; i < data.length; i++) {
url += "&" + data[i];
};
request.open("GET", encodeURI(url), async);
url = url.split('?');//get query string for remembered request
request.onreadystatechange = (remember) ? function() {responseAjax(element, url[0], loader, data.join('&'));}
: function() {responseAjax(element)};
request.send(null);
} else {
document.getElementById(element).innerHTML = "<h3>Browser Error</h3>";
};
};
Though I use eval() to handle returned script, the script doesn't work on events after all if I use pure javascript. However, if I use jQuery such as $("#tab-panel").createTabs();, this code works fine.
Can someone please explain why pure javascript on the loaded content of ajax doesn't work?
Additional information: As I said, pure javascipt such as function sent through the ajax content doesn't work on events, however another code such as alert() works fine.
I want to ask which code I need to write in order to invoke a doGet() in a Java Servlet. Right now the code I had written is:
function(){
var sURL = getUniqueSid("http://localhost:8080/Test/Sample?F=" + f + "&FB=" + fb);
var ret = xmlSyncHttpReq(sURL);
if (ret){
var params = new GG_ContainerParams("General");
var xTarget = params.dataSource;
var xElms = ret.selectNodes("Param");
for (var i=0;i<xElms.length;i++){
var x = xElms(i).cloneNode(true);
var chk = xTarget.selectSingleNode("Param[#Name = \"" + x.getAttribute("Name") + "\"]");
if (chk)xTarget.replaceChild(x,chk);
else xTarget.appendChild(x);
params.redraw();
}
}
function xmlSyncHttpReq(sURL,xmlSend,doThrow){
try{
var xmlhttp = new XMLHttpRequest();//ActiveXObject("Microsoft.XMLHTTP");
sURL = getUniqueSid(sURL);
xmlhttp.Open("GET", sURL, false);
xmlhttp.setRequestHeader("Content-Type", "text/xml");
if (typeof(xmlSend) == "object" && xmlSend != null)xmlSend = xmlSend.xml;
xmlhttp.Send(xmlSend);
if(xmlhttp.responseXML.documentElement){
if (checkErrors(xmlhttp.responseXML))return false;
else return xmlhttp.responseXML.documentElement;
}
xmlhttp = null;
return false;
}catch(e){
if (doThrow)throw e;
else alert(e.description);
return false;
}
}
Thanks in advance,
Tal Tchernihovski.
Pay attention to the JavaScript console in the browser. You should have seen the following error:
Uncaught TypeError: Object #<XMLHttpRequest> has no method 'Open'
JavaScript follows the Java naming conventions, not C# naming conventions. Methods start with lowercase. You need to use open() and send() instead of Open() and Send().
See also:
XMLHttpRequest documentation