JavaScript HTML Injection Error - javascript

I know some of the quirks of injecting HTML via JavaScript are subtle, but this one produces results which don't even make sense. I'm guessing some of the double quote characters are being misinterpreted, but the guides I've read don't seem to suggest doing anything different.
This is a function which injects a series of dynamically labelled buttons into a bootstrap panel and then injects that panel into a row on the page. So far I'm only producing 10 buttons, and I know I need to address the problem of having more than 12 and making a new panel. For now, the button creation is the issue.
function tableMaker(data, tableID) {
var panel = '<div class="col-md-12" style="height: 140px"> \n\t<div class="panel panel-default" style="height: 100%"> \n\t\t<div class="panel-heading">Apps Alive</div> \n\t\t <div class="panel-body">';
var mytable = '';
var colStart = '<div class="col-md-1"><center><b>';
var titleEnd = '</b></center>';
var buttonStart = '<center><button id="';
var buttonMiddle1 = '-appcheck" type="button" class="btn btn-default btn-circle btn-lg" title="';
var buttonMiddle2 = '" onclick="templateLoader("';
var buttonMiddle3 = '")"';
var buttonEnd = '-appcheck-icon" class="fa fa-exclamation-circle"></i></button></center>';
var colEnd = '</div>';
var panelEnd = '\n</div>';
var i = 0, j = 0, colLimit = 12;
for(; i < data.length;){
for (var j = 0; j < colLimit && i < data.length; ++j, ++i) {
/*
* Template
* <button id="OPS-appcheck" type="button" class="btn btn-default btn-circle" title="OPS" onclick="templateLoader("OPS")"><i id="OPS-appcheck-icon" class="fa fa-exclamation-circle"></i>
* </button>
*/
mytable += colStart + data[i][2] + titleEnd + '\n' + buttonStart + data[i][2] + buttonMiddle1 +
data[i][2] + buttonMiddle2 + data[i][2] + buttonMiddle3 + '><i id="' + data[i][2] +
buttonEnd + colEnd;
}
}
panel += mytable + panelEnd;
document.getElementById(tableID).innerHTML = panel;
}
To me, this looks right. Every quote and tag has a matching closer where it should be, but browsers turn the HTML generated into this odd thing:
The 'type' isn't in remotely the correct spot, and I don't know how it managed to get there based on the string format. There are also a few extra double quotes, but visual inspection doesn't tell me how they got there.
EDIT So, escaping the suggested double quotes has produced the following:
That seems like it should work, but the onclick isn't doing as I'd expect. It's probably a regex issue with my MVC mapping, but maybe it's still the JavaScript.
At the top of the HTML page, jquery.js and then dashboard.js are invoked. At the top of dashboard.js is the following:
function templateLoader(appTag) {
$.get('/app/' + appTag);
}
And in the controller for the project (the only one so far), I have this:
#RequestMapping(value = "/app/*", method = RequestMethod.GET)
public ModelAndView generic()
{
return new ModelAndView("template");
}
Yet, if I click any of the buttons, I get no reported request according to the Tomcat logs, and I'm not being redirected to my target page. Is it the mvc, or the script? There are no errors in the dev tools console either.

If you console.log(panel) at the end of your function, it becomes very clear
change these two vars
var buttonMiddle2 = '" onclick="templateLoader(\'';
var buttonMiddle3 = '\')"';

Related

Get Elements By Partial Attribute Value

I've been fiddling with this for several hours and I'm utterly stumped by its behavior. On JSFiddle, it seems to only be returning the values of the href attribute when I want the entire elements, but I can still use getAttribute(attribute) as if it's an element. In the userscript that this is for, it seems to completely break everything after calling the function(hence turning to JSFiddle and having no result to show here).
Why is this happening? How can I accomplish the stated goal?
HTML:
<a name="edit-a" href="http://example.com/edit1">foo</a>
<a name="moo" href="http://example.com/edit2">roo</a>
<a name="edit-b" href="http://example.com/boo">bar</a>
JavaScript function:
function getElementsByPartialValue(searchtext, searchattr, searchtag)
{
var searchreturn = [];
var searchreturni = 0;
var tagmatches = document.getElementsByTagName(searchtag);
for (var tagmatchesi = 0; tagmatchesi < document.getElementsByTagName(searchtag).length; tagmatchesi++)
{
if (tagmatches[tagmatchesi].getAttribute(searchattr).indexOf(searchtext) > -1)
{
searchreturn[searchreturni] = tagmatches[tagmatchesi];
searchreturni++;
}
}
return searchreturn;
}
Checking the result:
alert(getElementsByPartialValue('edit', 'name', 'a')[0]);
Result(https://jsfiddle.net/81s4g42a/3/):
http://example.com/edit1
Accessing other attributes(https://jsfiddle.net/81s4g42a/4/):
alert(getElementsByPartialValue('edit', 'name', 'a')[0].getAttribute('name'));
Result:
edit-a
Use Attribute-Contains Selector like this:
var tagmatches = document.querySelectorAll(searchtag + "[" + searchattr + " *= '" + searchtext + "']");
function getElementsByPartialValue(searchtext, searchattr, searchtag)
{
return document.querySelectorAll(searchtag + "[" + searchattr + " *= '" + searchtext + "']");
}
var elems = getElementsByPartialValue("edit", "name", "a");
for(var i = 0; i < elems.length; i++) {
elems[i].style.background = "red";
}
<a name="edit-a" href="http://example.com/edit1">foo</a>
<a name="moo" href="http://example.com/edit2">roo</a>
<a name="edit-b" href="http://example.com/boo">bar</a>
Use .querySelectorAll(), attribute is equal to or begins with followed by "-" selector
var tagMatches = document.querySelectorAll("a[name|='edit']");
console.log(tagMatches);
<a name="edit-a" href="http://example.com/edit1">foo</a>
<a name="moo" href="http://example.com/edit2">roo</a>
<a name="edit-b" href="http://example.com/boo">bar</a>
I hate to say this, but it's returning "name", not "href", if you want the url you should return the "href", not the "name"... Check your script and you'll find that you've set the name of the first tag to "edit-a", so when alerting the name of [0] you get "edit-a". If you access [1] you get "edit-b", and if you use 1 instead of 'name' you get "http://example.com/boo", and it's skipping the second one with "moo" as a name because you're only searching for ones with "edit" in its name, not its href/url.
alert(getElementsByPartialValue('edit', 'name', 'a')[0].getAttribute('href'));
I tested your code sample and find out, your code execute perfectly well. The problem is from the "alert()" function, try using console log, you will see that your code actually works.

JS for loop to fill array

Good day all and happy b-lated new year
So I got a problem and I would rather not tie everything directly into an array and call it from there. Im building an old school chat based RPG and I have hit an issue with passing on the skills which are determined by the characters stats. Essentially what I am trying to do is this:
I have a bunch of buttons which represent a total of 72 skills:
<td><button type="button" onclick="" class="button" id="math">MATH</button></td>
which I would like to use their onclick event to pass both the skill name and skill rating to this targeted area of the page:
<td><input type="text" id="skill1" value="" readonly /></td>
<td><input type="text" id="skillRate1" value="" readonly /></td>
the skillRate(s) are reflected in their appropriate variables like so:
var math = (mem * 3) + (log * 2);
and ideally what will happen is I set each targeted recipient in an array as skill and skillRate respectively so that once all the skills are selected it is stored in the array and uploaded into the DB as such.
Originally I was thinking something along the lines of this:
function addSkill(){
var n = 0;
for (n = 0; n < 17; n++){
getElementById("skill" + n) = getElementById(this.id);
getElementById("skillRate" + n) = //figure out some way to turn this into the var for skillRate (getElementById(this.id));
}
}
I've been bumbling around with this for days now but cant seem to get anywhere and I would really rather not just put all the skills and their respective skillRates in an array unless I have to.
Any thoughts or suggestions as to how to accomplish this or maybe another approach altogether?
Thanks in advance!
If i understood you problem properly, maybe you can do it this way:
For html
<td>
<button type="button" data-skill="math" data-point="20" onclick="addSkill(this)" class="button" id="math">MATH</button>
</td>
For javascript
//Start your variables
var tagsSkills = []
var totalPoint = 0;
function addSkill(skill) {
var dataset = skill.dataset;
totalPoint += dataset.point; // Here you will sum the skill's point
tagsSkills.push(dataset.skill); // Add skill into array
}
Or maybe, instead you could use a map structure that store map[skill] to points. And, just with skill in the function, you will have the points just getting it from the map.
Not sure why you don't want array, they are your friends.
This code will build a table from array but only uses it for build, all the calculations are later taken from html.
This is vanilla js, could be easier/prettier with jQuery.
JS:
//This is just for building the table, you don't have to use it if you don't want array for some reason :S
var skillsArr = [{
firstSkillName: "Memory",
firstSkillValue: 15,
secondSkillName: "Logic",
secondSkillValue: 17
}, {
firstSkillName: "Dexterity",
firstSkillValue: 12,
secondSkillName: "Speedness",
secondSkillValue: 11
}];
var table = document.getElementById("tblSKills");
var tableBody = table.createTBody();
for (i = 0; i < skillsArr.length; i++) {
var row = tableBody.insertRow(i);
var cell = row.insertCell(0);
cell.innerHTML = skillsArr[i].firstSkillName + ": " + "<span>" + skillsArr[i].firstSkillValue + "</span>";
cell = row.insertCell(1);
cell.innerHTML = skillsArr[i].secondSkillName + ": " + " <span>" + skillsArr[i].secondSkillValue + "</span>";
cell = row.insertCell(2);
cell.innerHTML = "<button onclick='doMath(this)'>DO THE MATH</button>";
}
function doMath(currnetBtn) {
var currentRow = currnetBtn.parentElement.parentElement; //TD -> TR
var currentCells = currentRow.children;
var skill1 = document.getElementById("skill1");
var skill2 = document.getElementById("skill2");
var mathResult = document.getElementById("mathResult");
skill1.value = currentCells[0].innerText;
skill2.value = currentCells[1].innerText;
mathResult.value = (currentCells[0].children[0].innerText/1) * 3 + (currentCells[1].children[0].innerText/1) *2 ;//This is your *3 + *2 function or whatever you want.
//You can also make that each skill set will have its' own math function.
}
HTML:
<h1>
Welcome to my skill page!
</h1>
<h2>
Your results:
</h2>
<label id="lbl1"></label>
<input id="skill1" readonly />
<label id="lbl2"></label>
<input id="skill2" readonly />
<label>Result:</label>
<input id="mathResult" readonly />
<table id="tblSKills">
</table>
-- Fiddle --

How to insert HTML elements in a div element using JavaScript?

How to produce all this code into a div element using JavaScript.
<div id=parentDiv>
<div id="question1">
QuestionNo 1
<button onclick="setOption(1,1)">A</button>
<button onclick="setOption(1,2)">B</button>
</div>
</div>
I want to insert the div question1 'n' number of times with ids as question2, question3 also the the parameters for calling the function setOption should be like setOption(i,1), setOption(i,2) for every questioni.
I have tried using this.
var paper = document.getElementById("paper");
for (i = 1; i <= NOQ; i++) {
paper.innerHTML += '<div id="question' + i + '">'
var element = document.getElementById("question" + i);
element.innerHTML += 'QuestionNo ' + i + ' :';
element.innerHTML += '<button onclick="setOption(' + i + ',1)">A</button>';
element.innerHTML += '<button onclick="setOption(' + i + ',2)">B</button>';
}
However, this method takes a lot of time when value of n goes more than 200 or so, which makes me think of a loading screen. But the problem is all the n element are banged on the screen at once and not one by one, and same happens with my loading screen. The loading screen is also banged with the other elements at the end of the process.
My questions are, Is this method legal at all? Why is this taking so much amount of time? Is the appendchild method better than this (if yes can someone help me how to insert all this using append child method)? How can i show a loading screen showing progress as each element loads?
I've fixed a few errors but you get general idea.
var paper = document.getElementById("paper");
for(i=1; i<=NOQ; i++){
paper.innerHTML+='<div id="question'+i+'"></div>'
var element = document.getElementById("question" + i);
element.innerHTML='QuestionNo '+i+' :<button onclick="setOption('+i+',1)">A</button><button onclick="setOption('+i+',2)">B</button>';
}
This shouldn't take long to load.
If you are getting long load times, consider pagination.
Check this code:
HTML
<div id=parentDiv>
<div id="question1">
<script>
fn_generate(10);//give any no. in place of 10 i.e. the no of qstns you want.
</script>
</div>
</div>
JavaScript
fn_generate=function(n)
{
for (i=1; i<=n; i++)
{
document.write("QuestionNo " + i);
for(j=1; j<=2; j++)
document.write("<button onclick='setOption("+i+","+j+")'>Ans" + j + "</button>");
document.write("<br>");
}
}

Using javascript/regex to filter through dynamically generated <input> tags

I am currently trying to create a dynamic printable-document generator for my training department at work. I would like the entire project to remain in Javascript/browser-side scripting, as I'm trying to gain knowledge in Javascript exclusively. The UI is linked below (can't post images until I have 10 rep):
Hosted on my personal website - cgiv.webs.com/Test Platform/Training Plan.png
The issue I'm having is with regular expressions. I am fairly new to Javascript, but VERY new to regular expressions within Jscript. I'm currently using the following function to generate and identify three input texts per execution:
/*Variable Declarations*/
var i1 = 0;
var i2 = 0;
/* ------------------- */
function generateInput()
{
if (i1<15)
{
i1++;
var appendSpan = document.getElementById('appendSpan');
var appendStr = "<div class='row'><input id='text_topic" + i2.toString() + i1.toString() + "' class='text_topic' type='text'/>|<input id='text_instructor" + i2.toString() + i1.toString() + "' class='text_instructor' type='text'/>|<input id='text_date" + i2.toString() + i1.toString() + "' class='text_date' type='text'/></div>";
appendSpan.innerHTML += appendStr;
}
else
{
alert("Action Cancelled. Maximum fields reached.");
}
}
The i2 variable indicates the header number that the input fields fall under, where the i1 variable indicates the row that each cell falls into. I would like to place a regex identifier script within the following function to pull the values from each cell and append them underneath their respective target spans within the "newPage" variable:
function createPage()
{
var newPage = "<html><head><title></title>";
newPage += "<link rel='stylesheet' lang='text/css' href='output.css'>";
newPage += "</head><body>";
newPage += "<div class='head'>" + promptVal[0] + "</div><br/>";
newPage += "<span id='hcontent1'></div></span>";
var inputs = document.getElementsByTagName("input");
/* Uhhh.. Yeah. This is where I'm lost */
newPage += "</span>";
newPage += "</body></html>";
var j = window.open('')
j.document.write(newPage);
j.document.close();
}
Once I can get, for example, text_(topic, instructor, date)(11-13) all within the "hcontent1" span, I can format it out. I just want the data to be pulled from the text fields and placed into div tags on a separate page.
Thanks for your time, ahead of time!
I figured it out! After like three days of searching, this worked:
var regex1 = /1/g;
for (var i=0; inputs[i]; i++)
{
if (inputs[i].id.search(regex1) == 10)
{
alert("It worked");
}
else if (inputs[i].id.search(regex1) == 15)
{
alert("It worked again");
}
else if (inputs[i].id.search(regex1) == 9)
{
alert("You did it, man");
}
else
{
alert("Skip this one");
}
}

Submit not working in Chrome and IE under Windows 7

I have a web form created using .net and in this form has a frame which has its source from another HTML page (created by courselab software). I call a JavaScript code whenever the user completes the page and click a submit button and exits normally or whenever the user navigates away from the page based on the JavaScript event onbeforeunload.
The code works just perfectly using:
Firefox in both cases
IE on Windows XP in both cases
Still it works in CHROME if the user clicked on the submit button (this submit button generated by courselab software which calls the JavaScript code),
but if the user navigates away from the web form, this code is being called using the onbeforeunload and the code renders correctly but the submit input is never fired.
Similarly this code does not fire using IE on Windows 7.
I have also called the code onunload of the form, but still nothing happens.
Update
IE 8
Firefox 3.6.1.3
Chrome 9.0.597.98
The main web form has the following:
<div id="FOContent">
<iframe runat=server id="mainiframe" name="mainiframe" scrolling="no" frameborder="no"
width="1000" height="920"></iframe>
</div>
The frame content comes from this HTML page:
<body style="margin-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;" onload="Run(true)" onunload="Shutdown()" onbeforeunload="Shutdown()" oncontextmenu="return false">
<div id="boardFrame" style="position:absolute;left:0px;top:0px;width:1000;height:700">
</div>
<div id="divEmail"></div>
</body>
And the JavaScript code being called for onunload or onbeforeunload is:
function LMSShutdown() {
if (submit_Var == false) {
var sAiccData = AICC_PrepareData(); // prepare data from the CourseLab
var strQuizResults
strQuizResults = "";
var nPos1 = sAiccData.indexOf("Score=");
nPos1 = nPos1 + 6;
var ePos1 = nPos1 + 2
var score = sAiccData.substring(nPos1, ePos1);
var sHTML = "";
var qTxt;
qTxt = ""
var qrStr = window.location.search;
var spQrStr = qrStr.substring(1);
var arrQrStr = new Array();
// splits each of pair
var arr = spQrStr.split("&");
for (var i = 0; i < arr.length; i++) {
// splits each of field-value pair
var index = arr[i].indexOf("=");
var key = arr[i].substring(0, index);
var val = arr[i].substring(index + 1);
var id1
var id2
if (key == "")
{key = "Q"+i}
qTxt = qTxt + "&" + key + "=" + val;
if (i == 0)
{ id1 = val; }
else
{ id2 = val; }
}
// saves each of field-value pair in an array variable
sHTML += '<FORM id="formQuiz" method="POST" action="../../../StudentView/QuizProcess.aspx?submit_Var=' + 'false' + '&score=' + score + qTxt + '">';
var spQrStr = g_arVars["writing"];
var arrQrStr = new Array();
// splits each of pair
var arr = spQrStr.split("###");
for (var i = 0; i < arr.length; i++) {
// splits each of field-value pair
var index = arr[i].lastIndexOf(":");
var key = arr[i].substring(0, index);
var val = arr[i].substring(index + 1);
if (key != "")
{qTxt = qTxt + "&" + key + "=" + val;
sHTML += '<INPUT TYPE="hidden" NAME="' + key + '" VALUE=\'' + val + '\'>';
}
}
sHTML += '<br><input name="btnSubmit" id="btnSubmit" type="button"><br>';
sHTML += '</FORM>';
document.getElementById("divEmail").innerHTML = sHTML;
document.getElementById("formQuiz").submit();
submit_Var = true;
}
}
The QuizProcess.aspx page has not much in HTML, but it has vb .net code to store data to database
The issue is that the function LMSShutdown is being called in all browsers on different platforms, but the form QuizProcess is not being submitted only in (Chrome on Windows XP or 7 ) and in (IE 8 when using Windows 7) strangely works fine in IE 8 on Windows XP.
Sounds like a security restriction here. Try generating that form straight from ASP.NET instead of Javascript. This will help Chrome see it, as the will be in the raw html rather than virtual. Of course, all the 's to the form can be hidden, so it wont affect the presentation.

Categories

Resources