protractor - issues with scrolling into infinite scroller - angularjs

I have a protractor test looking for a record in my infinite scroller component like this.
searchPage.searchEntitlement('search criteria');
var myHiddenElementInScroller = element(by.repeater('result in ctrl.results track by $index').row(12));
browser.driver.executeScript(function () { arguments[0].scrollIntoView(); }, myHiddenElementInScroller .getWebElement());
myHiddenElementInScroller.click();
This is supposed to scroll to the element and click it. Instead its throwing me element not visible error.
Has anyone come across this situation? Any help greatly appreciated.

You might need to explicitly wait for the scrolling into view actually happen:
browser.driver.executeScript("arguments[0].scrollIntoView()", myHiddenElementInScroller.getWebElement()).then(function () {
myHiddenElementInScroller.click();
});
Or, with browser.actions():
browser.actions().mouseMove(myHiddenElementInScroller).click().perform();

In few scenarios the element which we are looking for will be covered with some other element from DOM.when protractor tries to click it,the click will be received by the element that covers the actual element. So in such situation you need to use native javascript click event. Look at the below code.
browser.executeScript("arguments[0].click()", myHiddenElementInScroller.getWebElement())
The above code will send a click event directly to the mentioned webElement even if it is visible or not.
NOTE: this is not the recommended way for clicking an element. but you can you this in scenarios where you have no other workaround to achieve the click event.

Thanks for all the responses. I was able to resolve this issue by using element(by.CssContainingText(cssSelector, searchText)) locator.

Related

Warning : Added non-passive event listener to a scroll-blocking 'touchmove' event when md-select is in md-tabs

I am facing a performance issue in my angularjs application using angular material.
I have an <md-select> with many options (around 1300) and this <md-select> is in an <md-tab> tag. On the page load, my page freezes. This is probably due to Google Chrome's event passive listener, because I get the following log in my js console :
[Violation] Added non-passive event listener to a scroll-blocking 'touchmove' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
You can find a codepen which reproduces my issue : https://codepen.io/jjalal/pen/vWxYbv.
When switching from Harry to John the page freezes (it is way more obvious on my application). If you open the js log and set the log level to 'All levels' (enable verbose level), you can see the 3000 logs (I have 3 select with 1000 options each).
I saw on some answers that I should set the event passive to true like this :
document.addEventListener('touchmove', function(e) {
e.preventDefault();
}, { passive: true });
But this didn't solve my issue.
Any help would be appreciated.
Very recently (two days ago) had a very similar issue and after hours of research I had to realize that this is something that won't be fixed in the near future. Please refer to this question and the accepted answer for explanation. (And also check out the angularjs github issue which has a tag 'won't fix')
Regarding a kind-of solution:
The problem is 100% with the browser (don't even try it in IE, it will freeze with a note 'long running script') and the DOM rendering and not in your code. So I kept trying and trying and trying, removed tiny parts of the DOM (complete container divs, buttons, paragraphs, whatever I could find) one by one. At one point I was able to identify what caused the issue. I had an item that was draggable which contained a clickable md-icon and that icon had an on-hover md-tooltip. Now you see it had 3 events (dragging the item, clicking on the button and hovering the button) which collided. After removing the md-tooltip it worked like a charm. My suggestion is for you to start identifying what exactly could be causing this. The real solution will have to wait...

How do I return focus to an element when the entire page changes?

I have a complicated setup. My application is driven by a set of "rules" which dictate what the user interface is. The UI is rendered by looping through the rules and creating the individual dropdowns. Initially, everything renders properly. However, once a user makes a change to the UI, other rules may be affected. In my application, an api call is made, which then returns a modified set of rules. In the attached plunker, I've simplified things such that only the new set of rules is applied, which causes the page to re-render. The problem is that my users would like to be able to tab between all of the entries on the page and make changes. However, once the page is re-rendered, the currently selected page element is now gone nothing has the focus. I've tried to put the focus back on the proper element by tracking a common Id, but to no avail.
Using either of these doesn't seem to work.
var el = document.getElementById(focusId);
el.focus();
angular.element(el).focus();
I've also tried using the autofocus attribute on the dropdown that I want to have focus, but that didn't work either. I'm using angularjs 1.2. Any ideas are appreciated.
http://plnkr.co/edit/ND9PKqULIOlixWR4XChN?p=preview
If you want to assign auto focus dynamically to a element on the DOM from angular you can use this:
var myEl = angular.element(document.querySelector('select'));
myEl.attr('autofocus',"attr val");
You can also pass in an id like: angular.element(document.querySelector('#focusId'));
You can look here for a prior answer which may be of some more help!
-Cheers!
Problem here is, you are trying to focus the element before the blur event completes. So you need to execute the focus code after blur event. Async execution of your focus code would solve the problem. You can use either setTimeout or $timeout.
setTimeout(function(){
angular.element('#'+focusId).focus();
/* //or
var el = document.getElementById(focusId);
el.focus();
*/
});
or
$timeout(function(){
angular.element('#'+focusId).focus();
/* //or
var el = document.getElementById(focusId);
el.focus();
*/
});
dont forgot to inject $timeout to your controller if you are using second code. Hope this helps :)

Trying to create a keyboard shortcut for a button using Angular

I want to be able to set a keyboard shortcuts for buttons in an application I'm building. I'd like to be able to pass in the keyboard button code as a parameter to make it configurable. Here's what I have so far using the documentation before I got stuck. HTML:
<div ng-controller="BtnCtrl">
<button class="primary-btn" type="submit" ng-keypress="press($event, '12')">Button</button>
</div>
JavaScript:
angular.module('App')
.controller('BtnCtrl', function ($scope) {
$scope.press = function($event, hotKeyRef) {
if ($event.keyCode==hotKeyRef) {
//need some code here to trigger the button press
}
}
});
So using my approach, I'm unsure of a) how to trigger the button press from inside the function and b) whether this is the correct way of passing in the keyCode data.
I might also be taking completely the wrong approach, so any other guidance would be appreciated.
Thanks
For the question a).
The main uses of a < button > html element is to fire an event on a click.
So if you want to use a keypress, why use this element ? I don't really see what you want to achieve. that seems controversal.
for b) :
By default, ng-keypress is intended to be used in an input element.
Otherwise, it seems that some posts, where I inquired, manage to make it work out.
You can see what it can look like, for example on this post (Is it possible to listen for arrow keyspress using ng-keypress?)
in which the person trying to setup the konami code.
Moreover, it seems that you can have trouble depending on which browser (Chrome, Firefox, Safari, IE) you uses. Be careful.
I hope this could help you.
hi there is an excellent plugin for your scenario u can check the below link
https://github.com/chieffancypants/angular-hotkeys/
u can also check the below stackoverflow link
What is AngularJS way to create global keyboard shortcuts?

Backbone JS - event problems adding multiple Views into same parent container

My code fetches a Collection from the server and iterates through it. For each model fetched it creates a View that is appended to the same parent element. Each of these views has a "click" event that triggers a function.
The problem is that clicking on any item in the list causes the event function to trigger for ALL elements in the list. The only workaround I have is to make the function itself dynamic and try to determine if it should run based on things like the ID of the item clicked:
'click .request_box': function(e) {
var myid = $(e.currentTarget).attr("id");
// code here which determines whether the function runs
}
}
This is a workaround, but it is also a hack, and I'm sure there has to be a better way of dealing with what must be a common problem (creating a list). Repeat searching around the web does not suggest any better way, so I am posting in the hope someone with more experience using Backbone can offer suggestions on a better way to approach this problem....
Thank you in advance.

Display n time ago on various items using jquery, [issue with new elements generated after the loading the DOM]

I am using Jquery plugin http://timeago.yarp.com/ for showing time.
Issue is timeago will not take effect for dynamically generated items.
$(document).ready(function() {
$(".timeago").timeago(); // works perfectly fine for the items which are loaded on page load
//$(".timeago").live(timeago()); // gives me an error ie timeago is not defined
//$(".timeago").live($(".timeago").timeago()); // gives me an error too much recursion.
jQuery.timeago.settings.allowFuture = true;
});
From some google search I got to know something ie:
Using live is the same as using bind, except that it is limited only to the events click, dblclick, keydown, keypress, keyup, mousedown, mousemove, mouseout, mouseover, and mouseup.
Now how can do it cause I dont have any click event? How can I bind this?
.live() and .bind() assign callbacks to event. In your case, you don't have an event to assign the function to and so it fails.
You can, in theory, assign your callback to a custom event. You will however have to manually trigger the event (using .trigger()) whenever your item is generated. For example:
$("abbr.timeago").live("timeago", function() {
$(this).timeago();
});
// ... and in the bit that generates your item
$new_item.trigger("timeago")
Demo: http://jsfiddle.net/ZjuW4/9
Of course, using .live() in this situation is purely academic and does not really serve a good purpose.
If you do have access to the code that's generating the items, you can simply chain in the call to .timeago() as the items are generated, i.e. http://jsfiddle.net/ZjuW4/3/
take a look in this topic
here was discussed how to put timeago on dynamically loaded items
for example the results of an ajax request.
Activate timeago on newly added elements only
PS: allowFuture does not have anything to do with putting timeago on newly created items on your page. it just allows dates in the future (f.e. "in 3 days", "next week")

Resources