AngularJS: cant get ng-if to limit a dataset properly in an ng-repeat - angularjs-ng-repeat

Banging head on wall, when really should be off consuming dangerous amounts of alcohol for the new year. Anyway.
I've recreated a problem I'm having in a project with some nice simple data. I know this must be a simple fix, but I'm not seeing it as I swear my logic is sound.
What I wanted to do, was limit a resultset to a certain amount of rows while using ng-repeat. I placed an ng-if on the data line checking for $index being within a range that I've used a slider/textbox to control. It seems that having an {a < x < b} scenario is somehow causing me grief and it always displays the greater value AFTER the initial load, when its showing a correct data subset.
<div ng-repeat="data in dataSet" >
<div ng-bind="data" ng-if="$index < (model + 5) && $index > (model -5)">
</div>
</div>
Change the slider or the input box and the magic is gone and the thing erupts.
Plunker of the issue.
http://plnkr.co/edit/4JXEp8r72QziRxWODUys

Related

Handling Element is not clickable at point (x, y). Other element would receive the click: With Capybara, ruby, Webdriver

I am writing a UI test that goes to a list of articles and selects the load_more button until this is no longer available (because all articles have loaded). The problem is the button has been hidden at this point rather than removed and is returning this error
Selenium::WebDriver::Error::UnknownError: unknown error: Element <div
class="">...</div> is not clickable at point (x, y). Other element
would receive the click: <div class="" id="" data-module-name="">...
</div>
(Session info: chrome=65.0.3325.181)
(Driver info: chromedriver=2.36.540469
ruby-2.5.1/gems/selenium-webdriver
3.11.0/lib/selenium/webdriver/remote/response.rb:69:in `assert_ok'
I have tried a few loop types but for this, if we assume I'm using
while world.page.has_load_more?
world.page.load_more.click
break if world.page.has_load_more? == false
end
The question is how do I tell Selenium this is ok and not to error, so I can continue with the next step in my test case(cucumber). I realise that the choice of loop type may also be incorrect, so feel free to suggest changes there as well.
Firstly, as Rajagopalan has pointed out, the error that you're getting is not that your element is not visible (as in hidden by CSS) but that it is overlapped by another element. You can call save_and_open_screenshot to see what element is overlapping the button (possibly a fixed footer, etc?). Make sure you've set the window size large enough so you don't have elements unintentionally overlapping and make sure you're running the latest version of Capybara since it attempts to deal with overlapped elements in selenium by scrolling them into view if possible.
Secondly, the loop in your question doesn't make a lot of sense having both the while and break since they check the same thing. Also, assuming the "load more" button is loading and appending to the page via AJAX, you probably need to wait for the new elements to load before checking if the button exists (click does not wait for actions to complete since it has no idea what actions could/would be triggered). That would then become a structure something like
while page.has_button?('Load More')
# Get the current number of visible articles
article_count = page.all('div.article').count # Use whatever selector would match an article in the list
# click the button
page.click_button('Load More')
# ensure more articles have loaded
expect(page).to have_css('div.article', minimum: article_count + 1)
end
Note: You'll probably want to change that to use whatever page object methods you are using (has_load_more?, etc) but the general logic should be correct

JQuery Waypoints - infinite scroll "shortcut" makes unnecessary and erroneous AJAX requests?

Running into a problem while trying to implement Waypoints infinite scroll example from http://imakewebthings.com/waypoints/shortcuts/infinite-scroll/.
Here is a JSFiddle to demonstrate my issue: http://jsfiddle.net/jmankin/75g6cap2/5/
HTML
<div class="infinite-container">
<div class="infinite-item">Not much content</div>
</div>
<a class="infinite-more-link"
href="/gh/get/response.html/jermifer/jsfiddle/tree/master/waypoints-infinite/"
>Loading...</a>
JS
var waypoint = new Waypoint.Infinite({
element: $('div.infinite-container')[0]
});
In instances where the 1st "infinite-more-link" is "above the fold" of the viewport on page load (i.e. the "inifinite-item" content is too short to require scrolling), the script correctly makes an AJAX call to the link href and loads the requested content.
However, it then prematurely--and seemingly incorrectly--proceeds to make the AJAX call to the 2nd "infinite-more-link" even though that is "below the fold" when it loads.
Secondly, from then on, scrolling to the bottom of the page (what would technically now be the 2nd "infinite-item" content element) will cause an AJAX call to the originally requested URL (the one that the client explicitly addressed), which is completely baffling. Under normal circumstances, it does this over and over again. In jsFiddle, it just does it the once, but that still gives you an idea of what I mean.
(Note: I'm not able to know ahead of time the length of the content I'd be loading, which is why I can't guarantee that the user will have to scroll down to see the 1st "infinite-more-link.")
I tried to contribute to solve this issue in the library in this link, please check that: https://github.com/imakewebthings/waypoints/issues/384 - Best wishes!

why does this happen in x-editable + ng-repeat

I have been exploring Angular X-editable project for a while and came across this odd behavior.
Whenever I click on any one of the 3 'select' components and try to change the value from the dropdown, the method 'showStatus(..)' gets fired for other components as well that are inside the ng-repeat boundary. (which you can check through the console.)
Can you please tell me why is this happening? Am I missing something.. ?
EDITED LINK -> Fiddle : http://jsfiddle.net/hrr4M/4/
<span ng-repeat="d in list" >
<a href="#" editable-select="d.status" e-ng-options="s.value as s.text for s in statuses">
{{ showStatus(d.status) }}
</a> <br/>
</span>
The problem you have is that your binding
{{ showStatus(d.status) }}
fires up the function for every item, because as every item gets populated, it just refreshes and fires again, all of them.
This is not the right place to set this up.
I set up a modified fiddle for you: http://jsfiddle.net/hrr4M/13/
Inside the link statement I added
onaftersave="showStatus($data)"
That way, you can fire a function after an item has been selected (see docs for onaftersave vs onbeforesave), and you can get the selected value using $data.
Now it works already. The problem is, that your binding is still using the same function, and therefore firing up all the time.
I duplicated the function and renamed it to repeatFiller with the same functionality but omitting the console logs, so you can see it works. You might tweak that a bit but I think it does what you need.

Performance issue in backbone template

I am having a performance issue with backbone template.
The situation is I have collection of model, each model have a field called 'isSelected'.
I need to render this collection with a template for each individual model. The 'isSelected' field is used for setting the checkbox in the template.
For the sake of discussion, the template is as following.
<div class='thumbnail'>
<input class='checkbox' type='checkbox' {[ if (isSelected) { ]} checked='checked'{[ } ]}
</div>
When I need to make the checkbox all selected, I will update the field to true for each model in the collection.
The code I used is
this.collection.each(function(e) {
e.set("isSelected", true);
});
However, this way is very slow, for a collection contains 25 items, it will take almost 10 sec to make all checkbox 'checked'.
I am expecting that it should least than 1 sec, if i use plain jquery.
Is there any problems with this approach? what's the best approach for this kind problem?
Why don't you set isSelected to true as default in the model? That way you don't have to loop through the collection to set each of them to true.
It's hard to tell what's taking up all the processing time with the amount of code you posted. My first guess would be the render function is being called multiple times. Creating and destroying templates kills performance. If you hard more code posted it might be easy to spot any problem areas.
You should render all of the HTML nodes that could possibility be need. After they are rendered save a jquery selector and use that to toggle the selected.
Most of the time it isn't JS or Backbone that is the bottleneck. It's that JavaScript is triggering the DOM, CSS or reflows constituently and the browser is doing way too much work.
I'm building a PerfView for for backbone. It can render a collection with 1,000,000 models and scroll at 120FPS on chrome. The code is on Github at: https://github.com/puppybits/BackboneJS-PerfView. There's a lot of optimizations in there and comments in the code. One of the techniques in there is sure to solve your issue.

Setting a text field that has a JQuery mask on it

Using watir-webdriver, I am trying to set the value for a text field.
browser.text_field(:id, "phoneNumbers_value_input").set("5555551234")
When I run that command, I can see that watir found the field because the cursor is set on that field however no text is entered. I have also tried the send_keys and append commands but nothing seemed to work. No exception is thrown from these methods.
The only difference I could find between this field and the other fields on the page(which all work fine) is that it has this JQuery mask on it.
$(selector).mask("(999) 999-9999");
Any ideas on how to set the text field?
Edit:
Some more of the Javascript:
selector = '#' + id(field.id) + '_input';
if (field.format == 'phone') {
$(selector).mask("(999) 999-9999");
}
HTML of the field:
<div id="phoneNumbers_value_form_item" class="form_item validated no_focus">
<label for="phoneNumbers_value" class="form_label">phone</label>
<input type="text" value="" name="phoneNumbers[][value]" id="phoneNumbers_value_input" class="text">
<div class="tip"> </div>
<div class="tip_validating">
</div>
<div class="tip_error">
</div>
</div>
I don't see any element in the HTML you provided that would match the text input field being addressed in the ruby code at the top of your posting. e.g. there is nothing there with an ID of 'phone'
Based on the HTML in your question, I would expect the following to work
browser.text_field(:id, "phoneNumbers_value_input").set("5555551234")
Looking at the sample page you linked in the comments, when I use google chrome and the "Inspect Element" function on the input field with the ID of 'phone' I see that there are a number of event listeners associated with the field (blur, focus, input, keydown, keypress, unmask)
The 'focus' one gets my attention in particular, and seeing it there on that field makes me think that you might then need to first fire an event against the same element, such as the onfocus event, in order to activate the field, then try to set the value.
You'll notice that when you manipulate things manually, the field starts out blank, but as soon as it gets focus it displays the format for the input mask to the user, it may well be that this needs to happen first, before it see's any kind of input.
EDIT: In this case, based on feedback from the questioner, the answer turned out to be that they needed to first fire the 'unmask' event against the text field, and THEN .set the value they wanted, in order for things to work correctly when automating the testing. This doesn't exercise the field masking functionality, but then again I doubt the test mandate in this instance is to extensively test a 3rd party (JQuery) addin, and they are more concerned with the business logic etc in the back end, thus simply being able to set the value without the masking code getting in the way is what is needed.
The problem has to do with focusing on the text field. Even with a .click() somehow webdriver ends up with the cursor at the end if the input field (see issue 2377). Pressing the HOME key moves the cursor to the beginning and allows you to type in the input field, and still have the mask functionality.
In Java:
WebElement txtPhone = getDriver().findElement(By.id("phoneNumbers_value_input"));
txtPhone.sendKeys(org.openqa.selenium.Keys.HOME);
txtPhone.sendKeys(phoneNumber);

Resources