Javascript: list.indexOf(elm+"") returns index, but list.indexOf(elm) returns -1 - indexof

I was writing a function to remove given elements from an array and then i came to this particular situation:
function removeStudent(elm, list){
var elmToDelete = list.indexOf(elm);
console.log(elm + " element");
the console shows -1, so the given element couldn't be found in the list. However, if a search it as a concatenated stirng, it will return the index of given element:
function removeStudent(elm, list){
var elmToDelete = list.indexOf(elm+"");
console.log(elm + " element");
For the record, I'm currently using Chrome version 57.0.2987.133 (64-bit) in Mac OS.

Related

Use Cypress functions on variables

I'm looping throw all of the .row and need to grab the inner elements within .row. Is there a way to do this? I wasn't able to find any documentation on this on Cypress' website.
let num = 0
cy.get('.row').each(row => {
let rowDiv = cy.get(row).get('div') // not correct
let rowBtn = cy.get(row).get('button') // not correct
cy.get(rowDiv).should('have.text', 'Task ' + num)
cy.get(rowBtn).should('have.text', "Btn ' + num)
num++
})
You can use cy.wrap() to turn the yielded JQuery elements back into Cypress Chainables. Additionally, cy.each() can yield you the index of the current iteration, so instead of having to use num, you could just use that index variable.
cy.get('.row')
.each((row, rowIndex) => { // yields JQuery element and current iteration
cy.wrap(row).find('div').should('have.text', `Task ${rowIndex}`);
cy.wrap(row).find('button').should('have.text', `Btn ${rowIndex}`);
});

RxJs, not display in dom, but console works

Why do the outputs only display in one of element
(#skip-result or #distinct-result) not both of them ?
but if i try outputting the result from those two observable
below to console it works
you can check code here
var input$ = Rx.Observable.fromEvent(input,'input')
var x$ = input$
.debounce(1000)
// skip two character in string, from input value
// then, display it in #skip-result
x$
.map(v=> v.target.value)
.filter(v=> v.length > 2)
.flatMap(v=>
Rx
.Observable
.from(v)
.skip(2)
.reduce((x,y)=> x + y)
)
.subscribe(s=>{
$('#skip-result').text('Skip Value is ' + s)
})
// search distinct in string, from input value
// then, display it in #distinct-result
x$
.map(e=> e.target.value)
.filter(e=> e.length > 0)
.flatMap(v=>
Rx
.Observable
.from(v)
.distinct()
.reduce((x,y)=> x + y)
)
.subscribe(x=>{
$('#distinct-result').text('Distinct value is ' +x)
})
In the JSBin you've referenced, you haven't imported jQuery, but you appear to be using the jQuery selector to set the contents of both the #skip-result and #distinct-result DOM elements. This will throw an error.
If instead you changed them to set the innerHTML property, which one subscription already looks to be doing, you should get your expected behaviour.
.subscribe(s => {
skipResult.innerHTML = 'Skip Value is ' + s
})
EDIT
After a second look, your markup isn't being closed properly. Specifically, #skip-result is being made a child of #distinct-result.

ptor.findElements always returns true

I have the following Code, which never runs the error portion
ptor.findElements(protractor.By.css(elementCss)).then(function (elems) {
element = elems;
elementFound = true;
// if element.all(...).count()
console.log("inside then clause , Element Found");
}, function (err) {
console.error("waiting for element( " + elementCss + " ) to be found " + currentCount + "/" + timeout);
}); //ptor.findElement
even if the elementCss ='abc', some junk value, it always resolve into then clause
and not into reject/error as that is a junk css name.
findElement on the other hand behaves as expected. am i missing something here ?
The API for findElement returns en error if the element is not found by the given selector.
The API for findElements is to return an empty list if the selector does not match any element.
From findElement documentation :
If the element cannot be found, a bot.ErrorCode.NO_SUCH_ELEMENT result will be returned by the driver

xpath: check if current elements position is second in order

Background:
I have an XML document with the following structure:
<body>
<section>content</section>
<section>content</section>
<section>content</section>
<section>content</section>
</body>
Using xpath I want to check if a <section> element is the second element and if so apply some function.
Question:
How do I check if a <section> element is the second element in the body element?
../section[position()=2]
If you want to know if the second element in the body is named section then you can do this:
local-name(/body/child::element()[2]) eq "section"
That will return either true or false.
However, you then asked how can you check this and if it is true, then apply some function. In XPath you cannot author your own functions you can only do that in XQuery or XSLT. So let me for a moment assume you are wishing to call a different XPath function on the value of the second element if it is a section. Here is an example of applying the lower-case function:
if(local-name(/body/child::element()[2]) eq "section")then
lower-case(/body/child::element()[2])
else()
However, this can simplified as lower-case and many other functions take a value with a minimum cardinality of zero. This means that you can just apply the function to a path expression, and if the path did not match anything then the function typically returns an empty sequence, in the same way as a path that did not match will. So, this is semantically equivalent to the above:
lower-case(/body/child::element()[2][local-name(.) eq "section"])
If you are in XQuery or XSLT and are writing your own functions, I would encourage you to write functions that will accept a minimum cardinality of zero, just like lower-case does. By doing this you can chain functions together, and if there is no input data (i.e. from a path expression that does not match anything), these is no output data. This leads to a very nice functional programming style.
Question: How do I check if a element is the second element
in the body element?
Using C#, you can utilize theXPathNodeIterator class in order to traverse the nodes data, and use its CurrentPosition property to investigate the current node position:
XPathNodeIterator.CurrentPosition
Example:
const string xmlStr = #"<body>
<section>1</section>
<section>2</section>
<section>3</section>
<section>4</section>
</body>";
using (var stream = new StringReader(xmlStr))
{
var document = new XPathDocument(stream);
XPathNavigator navigator = document.CreateNavigator();
XPathNodeIterator nodes = navigator.Select("/body/section");
if (nodes.MoveNext())
{
XPathNavigator nodesNavigator = nodes.Current;
XPathNodeIterator nodesText =
nodesNavigator.SelectDescendants(XPathNodeType.Text, false);
while (nodesText.MoveNext())
{
if (nodesText.CurrentPosition == 2)
{
//DO SOMETHING WITH THE VALUE AT THIS POSITION
var currentValue = nodesText.Current.Value;
}
}
}
}

How to apply successively two xpath expressions with libxml?

To sum up, i'm a totally beginner in libxml and I have to use an existing source code. The main idea is to apply a first xpath expression to extract a set of nodes from an xml file. Then, for each node, the second xpath expression shall be applied to extract some values.
Existing source code is:
int xt_parseXmlResult(xmlDocPtr doc, const char *xpath, assoc_arrayc_t expr, arrayc_t *result)
{
xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
// Register namespaces ...
/*
* Evaluate main xpath expression
*/
xmlXPathObjectPtr xpathNodes = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx);
/*
* Now we apply the xpath expressions on each node returned by the first xpath request
*/
// First loop is on the XML document as we have to create a new context each
// time we change the document
int nbDocs = xpathNodes->nodesetval->nodeNr;
for (row = 0; row < nbDocs; row++)
{
xmlXPathContextPtr subCtx = xmlXPathNewContext(doc);
// Register namespaces ...
// Update context to use the nodeset related to this row
subCtx->node = xpathNodes->nodesetval->nodeTab[row];
for (col = 0; col < expr.nbItems; col++)
{
// Evaluate expression
xpathRows = xmlXPathEvalExpression((xmlChar *)expr.itemList[col].val, subCtx);
result->data[(row + 1) * result->nbCols + col] = strdup((char *)xmlXPathCastToString(xpathRows));
xmlXPathFreeObject(xpathRows);
}
xmlXPathFreeContext(subCtx);
subCtx = NULL;
}
xmlFreeDoc(doc);
xmlXPathFreeContext(xpathCtx);
xmlXPathFreeObject(xpathNodes);
return 0;
}
I think that the problem comes from this line
// Update context to use the nodeset related to this row
subCtx->node = xpathNodes->nodesetval->nodeTab[row];
Because the second xpath expression is applied from the root of the xml file, not the root of each node.
Any idea on how to do such thing?
you could concatinate your xpath expressions.
edit
//FORECAST/DAY/descendant::content/meteo/desc should work
as i see in the xmlXPathContext::node is for internal library use, so we can not use it
Probably xmlXPtrNewContext should help, but i am not able to use it.
I currently do the trick with concatenating both xpaths and quering the whole.
The new xpath is: "(" + xpath1 + ")" + "[num]" + xpath2.
Where num can be replaced with any number betwen 1 and the size of xpath1 result set.
And it seem to work.
Some sample code. Modify to suit your needs and language. This is C#, but it should be largely the same. Notice the second xpath is not starting with a "/" and is using an instance of the node returned from the first one. Neither of the xpaths end in a "/".
XmlDocument doc = new XmlDocument();
doc.Load(docfile);
XmlNodeList items = doc.SelectNodes("/part1/part2");
foreach (item in items)
{
XMLNode x = item.SelectNodes("part3");
//Dostuff
}

Resources