Why does angularjs interpolation fail in IE 11? - angularjs

I have a simple directive that creates a toolbar from an array of tool objects
<div ng-repeat="tool in tb.tools">
<button id="{{tool.name}}" class="btn"
aa-tool-button="tb.state.selectedTool"
ng-click="tb.toggleSelected(tool)"
style="background-color:{{tool.color}}">
{{tool.caption}}
</button>
</div>
In Chrome, Firefox, Safari and Edge this works fine. But the button color isn't being interpolated in IE 11. The interpolation is failing for some reason. This is what shows up in the IE element inspector:
resulting in an empty style tag and default gray buttons.
Can anyone suggest a reasonable workaround for this?

This looks ugly, better use:
ng-style="{'background-color': tool.color}"
works fine

In short, avoid "{{value}}" syntax entirely.
Interpolation/Transclusion, in general, don't seem to work with Internet Explorer 10 and 11, at least in Angular version 1.5.5. It may have been fixed in a subsequent version.
The work around is to use ng attributes instead of using interpolation, and ng-bind (creating a span to bind too if needed) for generic text injection. These are probably best practice anyway.
Having debugged it, the underlying cause seems to be that ultimately j-query is used to set the text value of the node, which works fine with most browsers, as the text node is either implicitly present, or automatically created, but these versions of IE require a text node to be explicitly created first. A newer version of j-query may address this (we're using 2.2).
Further information can be found here:
https://github.com/angular-ui/ui-router/issues/615
https://github.com/angular/angular.js/issues/5025

Related

Cannot get XPath selector to work using Robocorp Selenium library

I am attempting web automation with a platform called Robocorp using the Selenium library.
When I run my program, I have no issues until I encounter this page where I am trying to get the program to click on the icon that says SQL.
I want the <a> element with the #href attribute.
Here are some (of many) XPaths I have tried that have all failed:
xpath://a[contains(#href,'sql_form.jsp')]
xpath://*[text()='SQL']
xpath://a[#target='frame2]
Snapshot of the element:
I circled the element in red ^^^
I cannot get the selector to be recognized on this page. I have tried adding delays, waiting until the element is active, waiting until the element is visible, etc.
Nothing seems to work.
Here is an image of the elements I am trying to select.
(The link in the href element takes me to the page I am trying to access).
I thought that the third one would for sure work but is still failing.
I am using a platform called Robocorp which only needs the raw selector to work (CSS or XPath)
I was unaware that iframe needed to be handled differently or that it even existed
https://robocorp.com/docs/development-guide/browser/how-to-work-with-iframes
I first needed to switch frames.
To identify the element with text as SQL you can use you can use either of the following locator strategies:
Using Wait Until Element Is Visible:
Wait Until Element Is Visible xpath=//a[starts-with(#href, 'sql_form.jsp') and #target='frame2']/font[text()='SQL'] 10 seconds
Using Wait Until Element Is Enabled:
Wait Until Element Is Enabled xpath=//a[starts-with(#href, 'sql_form.jsp') and #target='frame2']/font[text()='SQL'] 10 seconds
References
You can find a couple of relevant detailed discussions in:
How to click a row that has javascript on click event in RIDE
Robot Framework: Wait Until Element Is Visible vs. Element Should Be Visible, which one is better to use?

How can I access the selector field of a By object?

I'm using Java, Selenium Webdriver in Eclipse.
I wrote a helper method to wait for an element present, scroll to it, wait for the element to be visible and click it. Here's what I have:
protected void waitScrollWaitClick(By by, String scroll)
{
wait.until(ExpectedConditions.presenceOfElementLocated(by));
getJse().executeScript("$('.mCustomScrollbar#" + scroll + "').mCustomScrollbar('scrollTo',document.querySelector(\"" + by.selector + "\"), {scrollInertia:0})");
wait.until(ExpectedConditions.visibilityOfElementLocated(by));
getDriver().findElement(by).click();
Now the issue I'm having is in that second line in the method. I am passing a By object. This works for the conventional Webdriver methods on lines 1,3,4. But since we are using a custom scrollbar for our web app, I need to use that JavascriptExecutor class (the getJse()) to scroll on the proper div #id (thus passing in the 'scroll' argument). To use that JSE I just need the CSS selector, not the whole By object. If I add a breakpoint and look, the By object contains a 'selector' field that has what I want (in Eclipse there's a red square icon with an 'F' on it), but I can't seem to access it. I tried with the "by.selector" in the code above, but that is a compile error.
How can use that selector field? I'm not Java expert, so maybe I'm missing something obvious. I guess I don't understand why I can stop on a breakpoint, see the By object I created in the Variables tab, expand the By object and see the 'selector' field I want, but just can't access it.
The easy answer is that you cannot get the CSS selector from a By type, or even WebElement type. This is because the WebElements themselves are found by the By class. In case the By specified was a xpath there would be no way to populate the CSS selector.
The long answer specifically for your issue, to get the CSS Selector would be to create it using Javascript. An example would be Florent B.'s answer here. However, I didn't tried myself and I have no idea if it works for all cases.
Now, to address the general issue, instead of using document.querySelector use document.getElementById in case your element has an id.
Or by using document.evaluate to get your element by xpath. You can find an example in the answer posted here.

Is there a way to make Webstorm beta 9 do live expression updates in angular?

I can debug my AngularJS app with chrome and when I change text in a tag for example the text changes as I type it. However, if I have an expression like {{1+1}} and change that to {{1+2}} what I see is the raw expression and not the evaluated one.
is this something I'm doing wrong or does webstorm not support it.
**Edit: I just create a short video to show what I mean
https://www.dropbox.com/s/2wnu969hi1ykxv0/webstorm9angularlive.mp4?dl=0
Known issue, please follow WEB-6471 for updates

Are there any tools for recording web browser events for seleniumn2?

I am looking for something very simple. It can use the Selenium IDE recording tool, but it does not allow me to pick what kind of locators I get.
I want to use:
driver.findElement(By.className(str))
to locate things. All I need is something which watches which UI elements on a web page get clicked and writes out the class attributes of those tags.
If I use the Selenium IDE recording (and export to the right type of thing), I get:
#Test
public void testNav() throws Exception {
driver.get(baseUrl + "/");
driver.findElement(By.name("3.1.1.5.1.1")).clear();
driver.findElement(By.name("3.1.1.5.1.1")).sendKeys("dan");
driver.findElement(By.name("3.1.1.5.1.5")).click();
driver.findElement(By.linkText("Products")).click();
driver.findElement(By.linkText("Categories")).click();
driver.findElement(By.linkText("Create a Category")).click();
driver.findElement(By.linkText("Cancel")).click();
driver.findElement(By.linkText("Products")).click();
driver.findElement(By.cssSelector("a.DisplayAdminProductsLink")).click();
driver.findElement(By.linkText("Product1")).click();
There are problems with this. First, it is not give me any By.className() calls. Why? Those first 3 calls will not help me. The framework I am using puts arbitrary things into the name. How can I get it to see the class attribute?
There actually are unique words in the class attribute of all of the above tags. I design my apps so that this is so. Yet it will not use them.
Earlier I asked:
Why is it doing a "driver.findElement().click()"? This is fragile and does not
end up working.
What I need is:
elt = driver.waitFor(By.className("c")); elt.click();
This will work reproducibly.....
I am considering to be removed from the question, as the findElement() code does work. You need to set a general time-out on the driver. It is not very obvious that this can be done, but it can.
So, continuing on....
I can go to the "Options" and change the order of the "Locator Builders" in eclipse. I can put "css" at the top. Then I get:
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.1\"]")).clear();
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.1\"]")).sendKeys("dan");
driver.findElement(By.cssSelector("input[name=\"3.1.1.5.1.5\"]")).click();
The tags are like:
<input class="form-control LoginUsernameField" ... />
But it does not see the class attribute.... Or I can do this manually.
Selenium looks for a unique identifier to identify elements in a webpage. classNames are a very less desired option for this purpose as they are generally not unique. Ids and names on the other hand are generally unique. This might be the reason why Selenium IDE is not selecting classNames and going for other identifiers.
Selenium IDE records user actions. You would have clicked on the element for Selenium IDE to identify it and that is why you are getting driver.findElement().click().
If you want to wait for element to wait you can try implicit wait.
When you want to use driver.findElement(By.className(str)), are you sure that there is one and only one element in the webpage that is associated with a className? If that is the case you can modify the webdriver code manually to use className.

with HTMLpurifier, how to add a couple attributes to the default whitelist, e.g. 'onclick'

Two questions:
I have been reading docs and SO posts.. and know how to do it the long way (defining each and every element and attribute myself), but all I want to do is add 2 or 3 attributes to the default whitelist.. so that I do not have to constantly find and add more elements/attributes to, e.g., HTML.AllowedElements and/or HTML.AllowedAttributes.
Specifically, now, (for internal trusted users) I need to allow javascript attributes (input from tinymce). Question #1.) Is there a way to just add an attribute (to what HTMLpurifier allows) without causing the whole default sets of allowed elements/attributes to be effectively wiped out (overwritten by ONLY what is explicitly written in HTML.AllowedElements or HTML.AllowedAttributes)?
For what I need right now (the javascript attributes), I got excited when I saw in this thread:
Whitelist Forms in HTML Purifier Configuration
...where Edward Z. Yang says, "... [$config->set('HTML.Trusted', true);] allows JavaScript."
...but even after setting this: $config->set('HTML.Trusted', true);, HTMLpurifier 4.4.0 is still stripping e.g. any input onclick="dostuff();" attribute. Why? Question #2.) Is there a quick way to add just the javascript attributes to the allowed list?
You're losing onclick because HTML Purifier doesn't know about that attribute, and if HTML Purifier passed everything through when you turned on %HTML.Trusted you might as well just not use HTML Purifier at all.
HTML Purifier has attribute collections for just this case; 'Common' is probably the right one to insert them into.
But... why? The real name of %HTML.Trusted really should be %HTML.UnsafeMakeMyApplicationVulnerable
HTMLPurifier does not support onClick and similar java script related attributes to any HTML element as a default behaviour.So if you wish to allow such attribute any way, you may add such attribute to specific element in following way.
$config = HTMLPurifier_Config::createDefault();
$def = $config->maybeGetRawHTMLDefinition()
$def->addAttribute('a', 'onclick', 'Text');
But be careful, this may lead to xss attack as you are allowing any java script code to be there in that attribute.

Resources