I have this piece of code here, that's supposed to find an HTML element on this Reddit page and then return a value from it, and then store that in a zero-based 1d array. (I have an internet explorer instance called IE)
Dim awardelements As Object
Dim awards As String
awardelements = IE.document.querySelector("#siteTable > div")(0)
awards = awardelements.getAttribute("data-gildings")
results(i + 1, 14) = awards
So I'm trying to get the value of "data-gildings" (the # of awards the post got), but I'm getting an automation error on the awardelements = IE.document.querySelector("#siteTable > div")(0) line. I'm not sure I can use the JS querySelector like that tbh so that might be the problem. I'd appreciate it if someone could point me in the right direction!
Thanks ^^
querySelector returns a single node not a collection you can index into. And you need Set keyword as mentioned.
Dim awards As Object, awardCount As String
Set awards = ie.document.querySelector("#siteTable > div")
awardCount = awards.getAttribute("data-gildings")
Related
Good day everyone,
I am currently trying to append a metadata file. Sorry in advance if I did anything wrong, I am unfamiliar with editing XML codes in JS.. Thanks!
Currently, I am having difficulty getting the results that I expected. I am trying to insert 2 new nodes one nested over the other into the newParentTestNode.
I want to add a couple of nodes within the TestNode as seen in the results I want.. I can't seem to find a solution online. Please do help thanks!
I am currently getting this result:
<gmd:MTTEST><TESTNODE2/></gmd:MTTEST>
But the result I want is:
<gmd:MTTEST>
<gmd:TestNode>
<gmd:TestNode2>
</gmd:TestNode2>
</gmd:TestNode>
</gmd:MTTEST>
xmlTest: function (evt) {
if(this.item.metadata_standard_name == "Correct Data"){
xmlString = this.item.sys_xml_clob;
var metadataXmlString = jQuery.parseXML(xmlString);
let newParentTestNode = metadataXmlString.getElementsByTagName("gmd:MTTEST")
newNode = metadataXmlString.createElement("TestNode")
newNode2 = metadataXmlString.createElement("TestNode2")
let addMe = newNode.appendChild(newNode2)
newParentTestNode[0].appendChild(addMe)
xmlString = (new XMLSerializer()).serializeToString(metadataXmlString);
console.log(xmlString)
}
appendChild() returns the node that is appended not the parent node.
This means that newNode.appendChild(newNode2) returns newNode2, which you'll then append to your root node, effectively removing TestNode2 from TestNode and appending it directly to MTTEST.
You don't need to assign the result of appendChild to a new addMe variable because appendChild modifies the structure in-place, so you gain nothing from the return value (as you already have variables referencing both the parent and the child element). So in the end you just need to append newNode (which will already contain newNode2) to newParentTestNode.
Good evening, I am a beginner to QTP, I need help, I developed a complex procedure for the reading of the tariffs within a page (developed in Javascript) and programming with powerful descriptive, for each share untreated, recognize the object .getROProperty ("InnerText") and put it in a variable for me with databases.
Indexes are many but all have the same properties (micclass, html tags) only changes the class and html id.
Class and html id recover them to function as a dataTable.
I have created a specific function that deals with the reading of the indices on the basis of a pair of collection value able to define only the object.
This is the part of script (function) that i need to recognize objects:
Function recover_q_cvq (q_cvq_ogg, ogg_class)
' Dim variables
Dim object_collection
Dim r_object
Dim rate_cvq
Dim count_object
Dim rate_trim
print "Object:" & q_cvq_ogg
print "Class:" & ogg_class
' recover rate with object collection, micclass, html tag, class, html id
Set object_collection = Description.Create()
object_collection("micclass").Value = "WebElement"
object_collection("html tag").Value = "DIV"
object_collection("class").Value = ogg_class
object_collection("html id").Value = q_cvq_ogg
object_collection("visible").Value = "True"
Set r_object = Browser("(H) Gestione Quote").Page("(H) Gestione Quote").ChildObjects(object_collection)
r_object.RefreshObject
count_object = r_object.count
If count_object = 1 Then
rate_cvq = r_object(0).getROProperty("innertext")
print "Object rate: " &rate_cvq
rate_trim_cvq = Replace(rate_cvq,",","")
recover_q_cvq = rate_trim_cvq
'empty variables object_collection,r_object,count_object
Set object_collection = nothing
Set r_object = nothing
Set count_object = nothing
Else
print "Object is not collected"
print "Error:" & err.number
print DescribeResult(err.number)
End if
End Function
The script works well and I have the variable rate_cvq object that interests me only during the execution often that QTP stops recognize the object suddenly, for no apparent reason, and despite the collection is not complete and therefore not recognize the ChildObject collects the object. When it happens from then on no object is recognized until the end of the test.
This anomaly occurs randomly and never at the same point and this, the same rate in an execution is detected while in another not. This makes me think that the script does not have problems.
Can someone please help me? I have to add some other property to the script? where am I wrong? Thank you very much in advance for your reply.
Cristiano
I've been trying to create a news box for my website today and I have a problem. Let me explain what happens. I create a 2d array that contains the news (date and the news). I then loop through it to construct the news_string and then use that for the DIV's innerHTML. I have put a very simple version of it below
for (var i = 0; i < news.length; i++)
{
news_string.concat(news[i][1],"<br>");
}
document.getElementById("news-content").innerHTML = news_string;
However nothing appears. I have cut it down to the very minimal. No result. I have used alerts. Nothing appears. The news_string is blank regardless of the fact I put data into it. And even if I do gain a string nothing appears in the DIV box. What's causing this massive break?
The concat method returns a value, you have no variable assignement there to catch it...
From the docs (notice the bold part):
The concat() method combines the text of two or more strings and returns a new string.
So you should use:
news_string = news_string.concat(news[i][1],"<br>");
I'm new with Ajax.
I'm trying to parse this document.
I've gotten as far as the readystatechange, and it's fetching the XML. But I get confused when it comes to the childNodes and their values.
Here's a bit of the code. If I try to alert that first value, it comes up blank.
var clientList = request.responseXML.getElementsByTagName('client');
for (var i=0;i<clientList.length;i++) {
var client=clientList[i];
var clientName = client.childNodes[0].nodeValue;
alert(clientName)
As far as I understand it, based on the XML document, each "client" tag would have the following ChildNodes:
[0] : clientName,
[1] : clientStreetAddress,
[2] : clientCity
[n] : ...and so on...
So what am I missing here? Clearly I don't have my facts straight. Please help!
You should read the data from the XML using the names of the tags, not based on what order they happen to be. When the document is parsed it might contain textnodes for the whitespace between the elements, which would offset the indexes of the elements containing the data that you want.
var clientName = client.childNodes.selectSingleNode('./clientName').nodeValue;
Thanks to TeslaNick for suggesting I use XPATH instead. The answer was as follows:
var clientDoc = request.responseXML;
var clientName = clientDoc.evaluate("data/client[1]/clientName", clientDoc, null, XPathResult.STRING_TYPE, null).stringValue
Of course, I think this has to be modified to handle IE browsers, and the path has to be set to loop through the clients. However, the actual, simplest answer is above.
Thanks also to Guffa for helping!
How do I remove an items from a data bound array? My code follows.
for(var i = 0; i < listBox.selectedIndices.length; i++) {
var toRemove = listFiles.selectedIndices[i];
dataArray.splice(toRemove, 1);
}
Thanks in advance!
Edit Here is my swf. The Add Photos works except when you remove items.
http://www.3rdshooter.com/Content/Flash/PhotoUploader.html
Add 3 photos different.
Remove 2nd photo.
Add a different photo.
SWF adds the 2nd photo to the end.
Any ideas on why it would be doing this?
Edit 2 Here is my code
private function OnSelectFileRefList(e:Event):void
{
Alert.show('addstart:' + arrayQueue.length);
for each (var f:FileReference in fileRefList.fileList)
{
var lid:ListItemData = new ListItemData();
lid.fileRef = f;
arrayQueue[arrayQueue.length]=lid;
}
Alert.show('addcomplete:' + arrayQueue.length);
listFiles.executeBindings();
Alert.show(ListItemData(arrayQueue[arrayQueue.length-1]).fileRef.name);
PushStatus('Added ' + fileRefList.fileList.length.toString() + ' photo(s) to queue!');
fileRefList.fileList.length = 0;
buttonUpload.enabled = (arrayQueue.length > 0);
}
private function OnButtonRemoveClicked(e:Event):void
{
for(var i:Number = 0; i < listFiles.selectedIndices.length; i++) {
var toRemove:Number = listFiles.selectedIndices[i];
//Alert.show(toRemove.toString());
arrayQueue.splice(toRemove, 1);
}
listFiles.executeBindings();
Alert.show('removecomplete:' + arrayQueue.length);
PushStatus('Removed photos from queue.');
buttonRemove.enabled = (listFiles.selectedItems.length > 0);
buttonUpload.enabled = (arrayQueue.length > 0);
}
It would definitely be helpful to know two things:
Which version of ActionScript are you targeting?
Judging from the behavior of your application, the error isn't occurring when the user removes an item from the list of files to upload. Looks more like an issue with your logic when a user adds a new item to the list. Any chance you could post that code as well?
UPDATE:
Instead of: arrayQueue[arrayQueue.length]=lid
Try: arrayQueue.push(lid)
That will add a new item to the end of the array and push the item in to that spot.
UPDATE 2:
Ok, did a little more digging. Turns out that the fileList doesn't get cleared every time the dialog is opened (if you're not creating a new instance of the FileReferenceList each time the user selects new files). You need to call splice() on the fileList after you add each file to your Array.
Try something like this in your AddFile() method...
for(var j:int=0; j < fileRefList.fileList.length; j++)
{
arrayQueue.push(fileRefList.fileList[j]);
fileRefList.fileList.splice(j, 1);
}
That will keep the fileList up to date rather than holding on to previous selections.
I see one issue. The selected indices are no longer valid once you have spliced out the first element from the array. But that should only be a problem when removing multiple items at once.
I think we need to see more code about how you are handling the upload before we can figure out what is going on. It looks to me like you are holding a reference to the removed FileReference or something. The described problem is occurring when you upload a new file, not when you remove the selected one.
Do you mean to use listBox and listFiles to refer to the same thing?
I'm stepping out on a limb here, because I don't have a ton of experience with JavaScript, but I'd do this the same way that I'd do it in C, C++, or Java: By copying the remaining array elements down into their new locations.
Assuming that listFiles.selectedIndices is sorted (and its contents are valid indices for dataArray), the code would be something like the following:
(WARNING: untested code follows.)
// Don't bother copying any elements below the first selected element.
var writeIndex = listFiles.selectedIndices[0];
var readIndex = listFiles.selectedIndices[0] + 1;
var selectionIndex = 1;
while(writeIndex < (dataArray.length - listFiles.selectedIndices.length)) {
if (selectionIndex < listFiles.selectedIndices.length) {
// If the read pointer is currently at a selected element,
// then bump it up until it's past selected range.
while(selectionIndex < listFiles.selectedIndices.length &&
readIndex == listFiles.selectedIndices[selectionIndex]) {
selectionIndex++;
readIndex++;
}
}
dataArray[writeIndex++] = dataArray[readIndex++];
}
// Remove the tail of the dataArray
if (writeIndex < dataArray.length) {
dataArray.splice(writeIndex, dataArray.length - writeIndex);
}
EDIT 2009/04/04: Your Remove algorithm still suffers from the flaw that as you remove items in listFiles.selectedIndices, you break the correspondence between the indices in arrayQueue and those in listFiles.selectedIndices.
To see this, try adding 3 files, then doing "Select All" and then hit Remove. It will start by removing the 1st file in the list (index 0). Now what had been the 2nd and 3rd files in the list are at indices 0 and 1. The next value taken from listFiles.selectedIndices is 1 -- but now, what had been the 3rd file is at index 1. So the former File #3 gets spliced out of the array, leaving the former 2nd file un-removed and at index 0. (Using more files, you'll see that this implementation only removes every other file in the array.)
This is why my JavaScript code (above) uses a readIndex and a writeIndex to copy the entries in the array, skipping the readIndex over the indices that are to be deleted. This algorithm avoids the problem of losing correspondence between the array indices. (It does need to be coded carefully to guard against various edge conditions.) I tried some JavaScript code similar to what I wrote above; it worked for me.
I suspect that the problem in your original test case (removing the 2nd file, then adding another) is analogous. Since you've only shown part of your code, I can't tell whether the array indices and the data in listFiles.selectedIndices, arrayQueue, and fileRefList.fileList are always going to match up appropriately. (But I suspect that the problem is that they don't.)
BTW, even if you fix the problem with using splice() by adjusting the array index values appropriately, it's still an O(N2) algorithm in the general case. The array copy algorithm is O(N).
I'd really need to see the whole class to provide a difinitive answer, but I would write a method to handle removing multiple objects from the dataProvider and perhaps assigning a new array as the dataProvider for the list instead of toying with binding and using the same list for the duration. Like I said, this is probably inefficient, and would require a look at the context of the question, but that is what I would do 9unless you have a big need for binding in this circumstance)
/**
* Returns a new Array with the selected objects removed
*/
private function removeSelected(selectedItems:Array):Array
{
var returnArray:Array = []
for each(var object:Object in this.arrayQueue)
{
if( selectedItems.indexOf(object)==-1 )
returnArray.push( object )
}
return returnArray;
}
You might be interested in this blog entry about the fact that robust iterators are missing in the Java language.
The programming language, you mentioned Javascript, is not the issue, it's the concept of robust iterators that I wanted to point out (the paper actually is about C++ as the programming language).
The [research document]() about providing robust iterators for the ET++ C++ framework may still e helpful in solving your problem. I am sure the document can provide you with the necessary ideas how to approach your problem.