adding multiple tables from one Javascript function - javascript

Can someone suggest a solution for below:
I am taking inputs from a CSV file using javascript. On a button click, I would like to update two tables in HTML. I have set two dvis; dvCSV and alld.
When I click on button the table only gets updated in "alldc" not in "dvCSV".
If I remove var alld =......upto "alld.appendChild(table);" then only "dvCSV" table gets updated with the data.
var dvCSV = document.getElementById("dvCSV");
dvCSV.innerHTML = "";
dvCSV.appendChild(table);
var alld = document.getElementById("alld");
alld.innerHTML = "";
alld.appendChild(table);

Related

How to write a test of clicking on a table row?

A project includes a page on which exists a column showing foods associated with a meal and a (paginated) column of foods not associated with a meal. A script allows to click on a food in the paginated column, have that food removed from the list of available foods and appear in the list of associated foods. In the dev environment I can demonstrate that the script works.
In an effort to learn how to use Panther in testing I've tried to reproduce the effect of clicking on a food. The test code below hopes to show that the first row of the table of unassociated foods changes after a click. That test runs without error but fails. The question, then, is how or whether to make a test that shows a change in the table.
Edit: When I forced a Firefox client (static::createPantherClient(['browser' => static::FIREFOX]);) and adding PANTHER_NO_HEADLESS=trueto.env.test.local` the test ran slow enough for me to observe the first table row was removed. So somehow the test needs a way to read the new first row (and is different from how the test tries to do that now).
Edit 2: If I insert the lines $client->request('GET', 'http://diet/meal');$newCrawler = $client->clickLink('edit'); after executing the script I can get the test to pass. This seems to be a different test from expecting the test to pass without leaving and returning to the page. Or is it not possible to test without leaving?
Edit 3: Since Panther says it "can wait for asynchronously loaded elements to show up" I added a data attribute which increments on clicking. The test now includes the line $this->assertSelectorWillNotContain("document.querySelector('#mealid').getAttribute('data-rte')", $rteCount);. Nice, except that Panther returns Given css selector expression "document.querySelector('#mealid').getAttribute('data-rte')" is invalid even though a Firefox console with the identical selector returns an integer.
table row: <td data-foodid="185">dolor</td>
test code:
class MealTest extends PantherTestCase
{
public function testFood()
{
$client = static::createPantherClient();
$client->followRedirects();
$client->request('GET', 'http://diet/meal');
$this->assertPageTitleContains('Meals');
$crawler = $client->clickLink('edit');
$this->assertPageTitleContains('Edit Meal');
$foodLink = $crawler->filter('#meal_pantry td')->first();
$q = $foodLink->attr('data-foodid');
$client->executeScript("document.querySelector('#meal_pantry td').click()");
$client->waitFor('#meal_pantry');
$nextUp = $crawler->filter('#meal_pantry td')->first();
$p = $nextUp->attr('data-foodid');
$this->assertNotEquals($p, $q);
}
}
javascript:
$('td').on('click', function (e) {
var foodId = $(e.currentTarget).data('foodid');
var mealId = $("#mealid").data("mealid");
var tableId = $(this).parents('table').attr('id');
var pageLimit = $("#mealid").data("pagelimit");
$packet = JSON.stringify([foodId, mealId, tableId]);
$.post('http://diet/meal/' + mealId + '/editMealFood', $packet, function (response) {
editFoods = $.parseJSON(response);
var readyToEat = $.parseJSON(editFoods[0]);
var pantry = $.parseJSON(editFoods[1]);
var table = document.getElementById('ready_foods');
$('#ready_foods tr:not(:first)').remove();
$.each(readyToEat, function (key, food) {
row = table.insertRow(-1);
cell = row.insertCell(0);
cell.innerHTML = food;
});
var table = document.getElementById('meal_pantry');
$('#meal_pantry tr:not(:first)').remove();
$('li.active').removeClass('active');
$('li.page-item:nth-of-type(2)').addClass('active');
$.each(pantry.slice(0, pageLimit), function (key, array) {
food = array.split(",");
foodId = food[0];
foodName = food[1];
var row = table.insertRow(-1);
var cell = row.insertCell(0);
cell.innerHTML = foodName;
cell.setAttribute('data-foodid', foodId);
});
location.reload();
});
});
Turns out I've been using the wrong assertions. The eventual solution:
$client = static::createPantherClient();
$client->followRedirects();
$client->request('GET', 'http://diet/meal');
$this->assertPageTitleContains('Meals');
$crawler = $client->clickLink('edit');
$this->assertPageTitleContains('Edit Meal');
$rteCount = $crawler->filter('#mealid')->attr('data-rte');
$client->executeScript("document.querySelector('#meal_pantry td').click()");
$client->waitForAttributeToContain('#mealid', 'data-rte', $rteCount + 1);

Fetching values from an element in an iframe on the same domain

I'm trying to condense two processes down in to one by having the two pages I need on one page using an iframe.
I have a page that contains a text area (used for sending an email) and then I have a purchase reference page that contains the details of someones purchase.
I'm trying to append an iframe of the purchase page to the bottom of my email page and then grab some data that's on it and insert it in to the text area.
EDIT: This is what I have so far:
Script one
//Grabs the selected purchase number
var purchaseNumber = window.getSelection();
purchaseNumber = purchaseNumber.toString();
var purchaseTitle;
var purchaseNumber;
function frameLoaded() {
purchaseTitle = window.frames['purchaseIframe'].contentDocument.getElementById ('listingTitle');
purchaseNumber = window.frames['purchaseIframe'].contentDocument.getElementById ('auctionSoldIdDisplay');
purchaseTitle = purchaseTitle.innerHTML;
purchaseNumber = purchaseNumber.innerHTML
var purchaseDetails = purchaseTitle + " - " + purchaseNumber;
insertText = insertText.replace("PURCHASEDETAILS", purchaseDetails);
}
if(purchaseNumber.length > 0){
var purchaseIframe = document.createElement('iframe');
purchaseIframe.src = 'http://www.mysite.co.nz/Admin/Listing/PurchaseDisplay.aspx?asid=' + purchaseNumber + '&submit1=++GO++';
purchaseIframe.setAttribute("height","1000");
purchaseIframe.setAttribute("width","100%");
purchaseIframe.setAttribute("id","purchaseIframe");
purchaseIframe.setAttribute("onload", "frameLoaded();");
void(document.body.appendChild(purchaseIframe));
alert(purchaseNumber);
}
Script Two
//Gather the selected template
var selectedTxt = document.getElementById('txtEmailText').value;
//Change the selected txt to a string
var insertText = selectedTxt.toString();
var purchaseTitle = window.frames['purchaseIframe'].contentDocument.getElementById ('listingTitle');
var purchaseNumber = window.frames['purchaseIframe'].contentDocument.getElementById ('auctionSoldIdDisplay');
purchaseTitle = purchaseTitle.innerHTML;
purchaseNumber = purchaseNumber.innerHTML
var purchaseDetails = purchaseTitle + " - " + purchaseNumber;
insertText = insertText.replace("PURCHASEDETAILS", purchaseDetails);
//Pasting the variable in to the textarea
document.getElementById('txtEmailText').value = insertText;
Effectively I am highlighting the purchase reference number on the page then executing this script to open the purchase page using the highlighted number. I am then grabbing the text values of the elements I need and pasting them in to the text area.
I'm still pretty new to javascript and am teaching myself as I go.
If i run the above scripts one after the other then it works like a charm, however if I try to run them together with the second in an onload() function set to the iframe then it won't.
Any help would be greatly appreciated or if you could point me in the direction of an article to help.
My first thought is that the iframe is not fully loaded before you try to get the values from it. My thought would be to try adding an onload event to your iframe and then when it loads invoke a function that grabs the value.
I would add purchaseIframe.setAttribute("onload", "frameLoaded();"); to your purchaseIframe block and then add the frameLoaded() function to your script. something like:
function frameLoaded() {
var purchaseTitle = window.frames[0].document.getElementById("listingTitle" );
var purchaseNumber = window.frames[0].document.getElementById("auctionSoldIdDisplay");
console.log(purchaseTitle.innerHTML);
console.log(purchaseNumber.innnerHTML);
}
And see if something like that grabs the right values. If it does than you can plug it in where you need it.
Am I understanding your problem correctly?

Execute JS in sharepoint display template

In my sharepoint list, I am dealing with items that should have attachments. I customized the template so that it would allow me to add attachments, but I see no possibilities to mark attachments as mandatory. I managed to check for attachments with the script
<script type="text/javascript" language="javascript">
function PreSaveAction()
{
var elm = document.getElementById("idAttachmentsTable");
if (elm == null || elm.rows.length == 0)
{
document.getElementById("idAttachmentsRow").style.display=&apos;none&apos;;
alert("Please attach Documents");
return false ;
}
else { return true ;}
}
</script>
but I was only able to use it in a custom form (not the template). Since the template is used for pretty much any interaction with the list, I want to use it and would like to execute the js code after the template has loaded. The template is referenced in between the tags <ZoneTemplate> and </ZoneTemplate>. There's much more code inside that form, but sharepoint-designer won't let me edit anything apart the stuff between those two tags.
It's really frustrating, because I seem to miss an obvious point. Hope I delivered enough information as I am not used to work with sharepoint and it's forms and templates for them...
When you need to add a JavaScript to a list form, you can browse to the form directly. For example, if your list is called MyList, then the new item form would be at http://url/Lists/MyList/newform.aspx and the edit form would be at EditForm.aspx. Browse to the page or pages where you want to insert your javascript code, then under Site Actions, click Edit Page. Add a Content Editor Web Part and either insert the javascript directly into the HTML of the content editor web part or add a link to an HTML file that has the javascript.
As for marking an attachment as mandatory, you may just need to include some wording to the form that will instruct the user to click Attach File button. Maybe something like this that would add a row to the bottom of the form table
<script type="text/javascript">
function addRow() {
var required = document.createTextNode("*");
var table = document.getElementsByClassName("ms-formtable")[0];
var tbody = table.getElementsByTagName("tbody")[0];
var tr = document.createElement("tr");
var td1 = document.createElement("td");
td1.setAttribute("class","ms-formlabel");
td1.setAttribute("vAlign","top");
var h31 = document.createElement("h3");
h31.setAttribute("class","ms-standardheader");
var text1 = document.createTextNode("Attachment");
h31.appendChild(text1);
var span1 = document.createElement("span")
span1.setAttribute("class","ms-formvalidation");
span1.setAttribute("title","This is a required field");
span1.appendChild(required);
h31.appendChild(span1);
var td1.appendChild(h31);
var tr.appendChild(td1);
var td2 = document.createElement("td");
td2.setAttribute("class","ms-formbody");
td2.setAttribute("vAlign","top");
var text2 = document.createTextNode("Click the Attach File button in the ribbon to add an attachment");
var td2.appendChild(text2);
var tr.appendChild(td2);
var tbody.appendChild(tr);
}
</script>
This is pretty ugly and can be simplified with jQuery.
<script type="text/javascript">
function addRow() {
var h3 = $('<h3 class="ms-standardheader">Attachment</h3>').append('<span class="ms-formvalidation">*</span>');
var td1 = $("<td></td>").append(h3);
var td2 = $("<td>Click the Attach File button in the ribbon to add an attachment</td>");
var tr = $("<tr></tr>").append(td1);
$(tr).append(td2);
$(".ms-formtable").first().find("tbody").first().append(tr);
}
</script>
Keep in mind this is untested and probably has some bugs in it.

Javascript, creating a template for a textfield with subscript and superscript

I am rather new to JavaScript. In my experimentation with some sample code, I have created an html file which contains a table. In one of the table data fields I have a text type field. Is there a way to make a button that inserts a pre-defined template for entry that allows for manipulation? aka I press a button "money" that inputs an additional formatted text to "$0.00".
so for example
function input_button(){
var template = "$0.00"
var my_txt = document.getElementById("money");
my_txt.value += Template;
On a side note, what if I wanted to use subscript and superscript? I have tried utilizing the .sup() and .sub() methods, but it just inserts the tags and doesn't alter the aesthetics of the text. ( so in the table, it looks like
<sub> things to be subscript </sub>
opposed to
things to be subscript
I'm not familiar with any way to template text formats, so you might just have to hard code in the logic. As to your second question, when you use the .sup and .sub methods, are you inserting the result in the inner html? For example:
function helloWorldSuper(){
var str = "Hello World";
var result = str.sup();
document.getElementById("tableCell").innerHTML = result;
}
To apply a mask to the input field in order to auto-format values with a template you will need to listen to input key press events and handle according to your mask. There are some scripts that already do this, like Masked Input Plugin for jQuery.
If you want the input text to just have $0.00 as an initial value, it's quite easy to do.
You can create and insert a row into the table via JavaScript like this:
<html>
<body>
<button id="insertRowButton">Insert</button>
<table>
<thead>
<tr><th>Text</th><th>Input</th></tr>
</thead>
<tbody id="tableBody">
</tbody>
</table>
<script>
(function() {
// Elements used
var tableBody = document.getElementById('tableBody'),
insertRowButton = document.getElementById('insertRowButton');
// Create a new row template
function createRow() {
var tr = document.createElement('tr'),
tdText = document.createElement('td'),
tdInput = document.createElement('td'),
sub = document.createElement('sub'),
input = document.createElement('input'),
text = document.createTextNode('This is a text node '),
subscriptText = document.createTextNode('with subscript');
sub.appendChild(subscriptText);
tdText.appendChild(text);
tdText.appendChild(sub);
input.value = '$0.00';
tdInput.appendChild(input);
tr.appendChild(tdText);
tr.appendChild(tdInput);
return tr;
}
// Insert a new row into table
function insertRow() {
var tr = createRow();
tableBody.appendChild(tr);
}
// Bind events
insertRowButton.addEventListener('click', insertRow);
}());
</script>
</body>
</html>
Here is it at JSFiddle: http://jsfiddle.net/ck7qargw/
I'm a little confused but I'm making the assumption that you are trying to add sup/sub script via innerHTML?
var template = "<span class='supStyle'>$0.00</span>"
CSS:
.supStyle{vertical-align:top;font-size:smaller;}
Or, you can use a forloop:
mySup = document.getElementsByClassName("supStyle");
for (var i=0;i<mySup.length;i++)
{
mySup[i].style.verticalAlign = "sub";
mySup[i].style.fontSize = "smaller";
}

Modify innerHTML for table row in javascript in ie8?

I am trying to add create an editable table in HTML. So, I need to add rows, when user clicks on a button. Here is the code I am using.
//remove all old rows.
while (summaryTableElement.firstChild) {
summaryTableElement.removeChild(summaryTableElement.firstChild);
}
//add a new text area in the summary field.
summaryTableElement.innerHTML = "<textarea id='summaryTextBox' value='' onblur='saveSummary()'> </textarea> ";
This code works fine on Chrome and Mozilla. But, IE doesn't allow editing innerHTML. This HTML will be displayed inside a VB form, so I have "browser" and "webbrowser" controls available. Both of those controls use IE engine, so this code does not work there.
I have tried using firstchild.innerHTML instead so that I am not editing table row directly, and even that gave me same error.
I tried using WebKitBrowser. But, that causes an exception on load. Apparently that control uses some old method, and the method is changed. So, that control is out of question too.
Now, I am confused as to how to solve this problem?
Edit:
I found the issue with WebKitBrowser. It was specific to x86, while my project was targeting both x64 and x86. Switching it to x86 for both, worked. Although, webkit browser do not take return key values. So, I have a new problem. Pressing enter does not create a new line in table cell, and instead passes the event to vb form.
Edit:
Okay, so I tried working further with WebKitBrowser. But, that control gives me accessviolatedexception. So, I am thinking about going back to using the default browser control, for now.
As for default control, I checked further. Apparently, code works fine in IE9 and above. But, vb.net control uses some weird JS engine. So, I am receiving error only in vb control.
Here is the complete code for reference:
var summaryChanges = "";
var isSummaryClickable = true;
//creates a textbox for editing purpose and include the original summary data.
function modifySummary(id) {
var summaryTableElement; //to get the table cells so that we can access the value
var originalSummary = ""; //to hold the original summary while we create a text box
var loopCounter = 0;
if (isSummaryClickable == true) {
isSummaryClickable = false; //saves event spilling when clicked on the newly created textbox
//get the summary table id saved.
summaryTableElement = document.getElementById (id).childNodes.item(0);
//add existing data to a string to save it for later.
for (loopCounter = 0; loopCounter < summaryTableElement.childNodes.length; loopCounter++) {
originalSummary = originalSummary + summaryTableElement.childNodes.item(loopCounter).childNodes.item(0).innerHTML + "\n";
}
//remove all old rows.
while (summaryTableElement.firstChild) {
summaryTableElement.removeChild(summaryTableElement.firstChild);
}
//add a new text area in the summary field.
summaryTableElement.innerHTML = "<tr><td><textarea id='summaryTextBox' value='' onblur='saveSummary()'> </textarea></td></tr> ";
//set the width of the textbox to allow easy modification
document.getElementById("summaryTextBox").style.width = '600px';
//add original summary text to the text area and set focus
document.getElementById("summaryTextBox").value = originalSummary;
document.getElementById("summaryTextBox").focus();
}
}
// saves the updated summary data back to HTML
function saveSummary()
{
var newHTML = "";
var changesSummary;
var changesSubString = new Array();
var index = 0;
var elementToUpdate;
//get the summary table id saved.
elementToUpdate = document.getElementById("SummaryData"); //.childNodes.item(0);
//get changes from the textbox
changesSummary = document.getElementById("summaryTextBox").value;
//generate string array for separate lines from summaryChanges
changesSubString = changesSummary.split("\n");
//generate new HTML string for the summary fields
//alert(changesSubString.length);
for (index = 0; index < changesSubString.length; index++) {
newHTML = newHTML + "<tr><td class='Text' style='padding-left: 4px;padding-bottom: 4px;' id='SummaryLine" + index + "'</td>" + changesSubString[index] + "</tr>"
}
//update the HTML to the element
elementToUpdate.innerHTML = newHTML;
//allow clicking on summary table
isSummaryClickable = true;
}
function doNothing(id) {
//empty function for future use
return;
}
//this function is called from vb.net script to read the js variable.
//do not change the function definition (name or parameters or return type)
//any change will cause error in vb.net script
function jsInvokedFunction() {
var updatedHTML; // to be used by vb.net invoked function to get updated body
var testVariable = "test";
updatedHTML = document.body.innerHTML.toString();
return updatedHTML.toString();
}
I receive an error at the start of the line summaryTableElement.innerHTML = " ";
It is possible I am missing some other error, but I couldn't find any.

Categories

Resources