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.
Related
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}`);
});
I am attempting to use the .filter command of cy.get() to return multiple instances of a DOM object that has the same word, but different cases, and can't get it working.
Eg: I want the following code example to return both Hello, hello and even heLLo
cy.get('tbody tr')
.filter(':contains("hello")')
Update: One further piece of information that may affect things is what I am doing after this. Here's a beefier piece of code example:
cy.get('tbody tr')
.filter(':contains("hello")')
.within(() => {
cy.get('td').then(($rows) => {
<do stuff>
};
};
Is this even possible? According to the documentation here the text selection is case-sensitive, but I'm hoping there is another option, eg: am I able to use Regex in this instance instead?
Many thanks in advance.
You are quite right, .contains(...) is not the way, it only returns one result, in the docs
.contains() yields the new DOM element it found.
One way to filter by text case-insensitive is to use a .filter() with callback.
Testing this
<table>
<tbody>
<tr><td>hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>heLLO</td></tr>
<tr><td>goodbye</td></tr>
</tbody>
</table>
this test succeeds
cy.get('tbody tr')
.filter((i, el) => el.innerText.toLowerCase().includes('hello'))
.should('have.length', 3) // 3 out of 4 rows
or you can add your own pseudo
Cypress.$.expr.pseudos.containsInsensitive = function(a, i, m) {
return Cypress.$(a).text().toLowerCase()
.indexOf(m[3].toLowerCase()) >= 0;
};
cy.get('tbody tr')
.filter(':containsInsensitive("hello")')
.should('have.length', 3) // 3 out of 4 rows
or if you prefer regex
Cypress.$.expr.pseudos.match = function(a, i, m) {
const expr = m[3].split('/')[1]
const flags = m[3].split('/')[2]
const regex = new RegExp(expr, flags)
return regex.test(Cypress.$(a).text())
};
cy.get('tbody tr')
.filter(':match(/hello/i)')
.should('have.length', 3) // 3 out of 4 rows
How about you just use .contains() then you can pass the case sensitivity flag matchCase as false. Cypress Docs
cy.get('tbody tr').contains('hello', { matchCase: false })
I want to validate a value , which is dynamic and retrieved from one page to another. That element also has space on it.
Below is my coding for that.
Page - 1
var PerAge = element(by.css("h1 > span.ng-binding")).getText();
This element has space on it , like this - > name
Page-2 - > same value displayed in an other page. This element has no space on it.
var HumAge = element(by.repeater("slide in ctrl.slides track by $index")).getText();
Now, I want to validate the value on Page 2 is same or not. Since , the repeater has bunch of other values , so I am using .toContain to validate the value.
The issue here is , the PerAge has space on it.
I checked this stack overflow question , but it did not work.
Expected '> ' to equal '> ' in jasmine.
expect(PerAge).toContain(HumAge);
Its returning following error
Expected 'Shane' to contain ' Shane'.
I tried trim, It doesn't recognize trim.
I cannot use .ToEqual like below since the element have bunch of other things.
expect(PerAge).toEqual('\xA0HumAge')
If I understand you correctly, you retrieve a value on page 1 like this:
var PerAge = element(by.css("h1 > span.ng-binding")).getText();
and use it on page 2 to compare it:
var HumAge = element(by.repeater("slide in ctrl.slides track by $index")).getText()
expect(HumAge).toEqual(PerAge);
This fails due to the spaces.
The reason why you can't use .trim() is because .getText() returns a promise. You first need to resolve the promise before you can use .trim().
What you can do is for example this. You also find an example of the code if you use a transpiler like Babel or use TypeScript which both support Async/Await.
var PerAge, HumAge;
element(by.css("h1 > span.ng-binding")).getText()
.then(function(text) {
PerAge = text.trim();
});
// Go to page 2
element(by.repeater("slide in ctrl.slides track by $index")).getText()
.then(function(text) {
HumAge = text.trim();
});
expect(HumAge).toEqual(PerAge);
// If you can use async await because you transpile with Babel or use typescript you can do this to tidy the code
// $ is the Protractor shorthand for the `css`-locator
const PerAge = (await $('h1 > span.ng-binding').getText()).trim();
const HumAge = (await $('[ng-repeater="slide in ctrl.slides track by $index"]').getText()).trim();
expect(HumAge).toEqual(PerAge);
I have kendo numeric text box. If i type number like 123456, the widget automatically format the number with comma and dollar symbol as expected. However if i copy and paste number with comma, for example 123,456, the widget does not accept that as input.
JSfiddle demo
How do i fix this or override the defualt behavior
place comma by separated thousand value and place currency of country for Kendo grids
columns.Bound(e => e.Amount).ClientTemplate("#= Amount !== null ? kendo.toString(Amount, 'c', 'en-US') : ''#").Width("5%").Title("Amount");
For instance:
kendo.toString(1234.23, ‘c’, ‘de-DE’) –> 1.234,23 €
kendo.toString(1234.23, ‘c’, ‘sv-SE’) –> 1.234,23 kr
kendo.toString(1234.23, ‘c’, ‘en-US’) –> $1,234.23
only comma separated with two decimal points:
columns.Bound(e => e.Amount).ClientTemplate("#= kendo.format('{0:N2}', kendo.toString(Amount)) #").Width("5%").Title("Amount");
for Example - 1234.44 -> 1,234.44
1234 -> 1,234.00
I think it is a bug in Kendo...
In the source code for the NumericTextBox, there is a _paste handler that appears like it is trying to sanitize the input against the culture's numeric format but then it validates against the unsanitized value...seems to be it should use the sanitized value.
Here's the implementation:
_paste: function (e) {
var that = this;
var element = e.target;
var value = element.value;
var numberFormat = that._format(that.options.format);
setTimeout(function () {
var result = that._parse(element.value);
var isValid = that._numericRegex(numberFormat).test(element.value);
if (result === NULL || that._adjust(result) !== result || !isValid) {
that._update(value);
}
});
},
So, if you paste "123,456", it will _parse() it to 123456(because it knows that "," is the thousands separator) but then the isValid check is still checking against the "123,456" which is bad and so it reverts to the previous value.
If you change the isValid line to
var isValid = that._numericRegex(numberFormat).test(result);
so that it validates against the sanitized value, then it all appears to work as you expect it to....otherwise I can't really see why the sanitize it in the first place.
I realize that changing the kendo source code it not really a valid solution, but I do believe this is a bug that you may have to work around it until it is fixed.
If you have a kendo license, I would contact their support to verify if it is a bug or not. If you don't have a license, let me know and I will submit a request when I have time as I do have a license.
I have read a number of posts about this but none with any solid answer. Here is my code:
// button creation
onew = document.createElement('input');
onew.setAttribute("type", "button");
onew.setAttribute("value", "hosts");
onew.onclick = function(){fnDisplay_Computers("'" + alines[i] + "'"); }; // ie
onew.setAttribute("onclick", "fnDisplay_Computers('" + alines[i] + "')"); // mozilla
odiv.appendChild(onew);
Now, the setAttribute() method (with the mozilla comment) works fine in mozilla but only if it comes AFTER the line above it. So in other words it seems to just default to whichever gets set last. The .onclick method (with the ie comment) does not work in either case, am I using it incorrectly?
Either way I can't find a way to make this work at all in IE, let alone in both. I did change the function call when using the .onclick method and it worked fine using just a simple call to an alert function which is why I believe my syntax is incorrect.
Long story short, I can't get the onclick parameter to work consistently between IE/Mozilla.
-- Nicholas
onew.setAttribute("type", "button");
Never use setAttribute on HTML documents. IE gets it badly wrong in many cases, and the DOM-HTML properties are shorter, faster and easier to read:
onew.type= 'button';
onew.onclick = function(){fnDisplay_Computers("'" + alines[i] + "'"); }; // ie
What is ‘alines’? Why are you converting it to a string and surrounding it with single quotes? It looks like you are trying to do something heinous involving evaluating code in a string (which is what you're doing below in the ‘onew.setAttribute’ version). Evaluating JavaScript code in strings is almost always the Wrong Thing; avoid it like the plague. In the above case, IE should do the same as Firefox: it shouldn't work.
If ‘alines[i]’ is a string, I guess what you're trying to do is make it remember that string by constructing a code string that will evaluate in JavaScript to the original string. But:
"'" + alines[i] + "'"
is insufficient. What happens if ‘alines[i]’ has an apostrophe in, or a backslash?
'O'Reilly'
you've got a syntax error and possible security hole. Now, you could do something laborious and annoying like:
"'" + alines[i].split('\\').join('\\\\').split("'").join("\\'") + "'"
to try to escape the string, but it's ugly and won't work for other datatypes. You could even ask JavaScript to do it for you:
uneval(alines[i])
But not all objects can even be converted to evaluatable JavaScript source strings; basically the entire approach is doomed to failure.
The normal thing to do if you just want to have the onclick callback call a function with a parameter is to write the code in the straightforward way:
onew.onclick= function() {
fnDisplay_Computers(alines[i]);
};
Generally this will work and is what you want. There is, however, a slight wrinkle which you may have hit here, which could be what is confusing you into considering the wacky approach with the strings.
Namely, if ‘i’ in this case is the variable of an enclosing ‘for’ loop, the reference to ‘alines[i]’ won't do what you think it does. The ‘i’ will be accessed by the callback function when the click happens — which is after the loop has finished. At this point the ‘i’ variable will be left with whatever value it had at the end of the loop, so ‘alines[i]’ will always be the last element of ‘alines’, regardless of which ‘onew’ was clicked.
(See eg. How to fix closure problem in ActionScript 3 (AS3) for some discussion of this. It's one of the biggest causes of confusion with closures in both JavaScript and Python, and should really be fixed at a language level some day.)
You can get around the loop problem by encapsulating the closure in its own function, like this:
function callbackWithArgs(f, args) {
return function() { f.apply(window, args); }
}
// ...
onew.onclick= callbackWithArgs(fnDisplay_Computers, [alines[i]]);
And in a later version of JavaScript, you'll be able to say simply:
onew.onclick= fnDisplay_Computers.bind(window, alines[i]);
If you would like to be able to use ‘Function.bind()’ in browsers today, you can get an implementation from the Prototype framework, or just use:
if (!('bind' in Function.prototype)) {
Function.prototype.bind= function(owner) {
var that= this;
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner,
args.length===0? arguments : arguments.length===0? args :
args.concat(Array.prototype.slice.call(arguments, 0))
);
};
};
}
I usually use something like:
onew.onclick = new Function("fnDisplay_Computers('" + alines[i] + "')");
this should work both in IE e Firefox.
Use the addEventListener() function with "click" for the type argument for Mozilla-based browsers, and attachEvent() function with "onclick" as the sEvent argument for IE; I find it best to use a try/catch statement, for example:
try {
onew.attachEvent("onclick", //For IE
function(){fnDisplay_Computers("'" + alines[i] + "'"); });
}
catch(e) {
onew.addEventListener("click", //For Mozilla-based browsers
function(){fnDisplay_Computers("'" + alines[i] + "'"); },
false);
}
I think #3 protesteth too much. In a lot of situations I'm building a table dynamically and need to pass parameters to the callback function. It isn't a typesafe issue since my variable parm is an integer index to the table row in question. Here's code with both a variable and fixed parameter that seems to be cross-browser compliant:
for (i = 0; i < arrTableData.length; i++) {
eleTR = objTable.insertRow(i + 1);
cell = eleTR.insertCell(0);
cell.width = "21";
var myElement = document.createElement('img');
myElement.setAttribute('src', 'images/button_down.gif');
myElement.setAttribute('alt', 'Move item down');
myElement.onclick = new Function('moveItem(' + i + ',0)');
cell.appendChild(myElement);
}