jQuery queue and trigger - javascript

I have a dynamic page and am trying to build dynamic links (domain.com/#/page2/content/etc).
If the person enters a link, let's say domain.com/#/2010/05/14 I want it to click on the element #2010. $("#2010").trigger("click");
Then after the function loads, click on $("#05").trigger("click");
See what I'm saying? As of right now it works perfectly for the first one, but the second click runs before the other can load.

You will need to build a function that runs at the end of the click function of $('#2010') that checks if there is another link to click. You could build an array of components at page load and at the end of each click function check if there are any more parts of the array, if there are trigger the next click. Each time you go through remove the element from the array so that it won't be used again.

Related

How to find the first element if Xpath returns a list of elements(selenium-python)

browser = webdriver.Chrome(path)
browser.maximize_window()
browser.get("https://www.flipkart.com")
browser.find_element_by_xpath('//button[#class="_2AkmmA _29YdH8"]').click()
browser.find_element_by_name("q").send_keys("Mobiles")
browser.find_element_by_xpath("//button[#class='vh79eN']").click()
p = browser.find_elements_by_xpath("//div[#class='_3wU53n']")
Using the above code, I have to search for Mobiles in flipkart and click on any Mobile which should that open page onto new Tab.
I am facing issue with locating a mobile as Xpath returns a list of Mobiles. I want to find the first element and click so that it opens in new tab.
Can Anyone help me with this? Thanks!
When you used browser.find_elements_by_xpath("//div[#class='_3wU53n']") p will be a lists, so you can access items as easy as p[0], more info here.
But if you only need the first element, I suggest u should use browser.find_element_by_xpath("//div[#class='_3wU53n']") without the "s" as it should select the first element in that class
You can store in List by using list class in selenium.
List lists=driver.findElements(By.xpath(".."));
lists.get(0).click();
//Above code for click first element in lists
Once you "CLICK" the SEARCH button, the webpage redirects to a new page which shows the list of mobile. However, it takes some time to load the page. So you need to add some delay to it, so as to perform the next actions.
<the code above remains the same>
browser.find_element_by_xpath("//button[#class='vh79eN']").click()
import time
time.sleep(3) # Added a delay
browser.find_element_by_xpath("//div[#class='_3wU53n']").click() # Changed the "elements" to "element"
This opens the first mobile phone in the new tab.
PS. This code works great if you need only the first mobile. If you need all the mobiles on the page, you will have to create a loop for it!

How to use the back button correctly?

I have a problem with back button in my app.
I mean I am using react-router-last-location to know my last page:
const backUrl = this.props.lastLocation ? this.props.lastLocation.pathname : MAIN_PAGE;
The problem is:
e.g. From main page "/" I clicked to "cards" and my route changed to "/cards", then I clicked to any card and my route changed to "/card/64531", then I clicked to information tab and my route changed to "/card/64531/info".
If I try to use back button from last page ("/card/64531/info") my route will be changed to "/card/64531". Then if I try to use back button my route will be changed to "/card/64531/info", and this will be change in a circle. How to fix it?
From the top of my head, I would implement a LIFO (Last In Frist Out) stack, where you push every url change to that stack and then take out the last elements from it on every back button press.
Just make sure you are not adding to the stack urls that are triggered by the back button.

How can I overwrite a function in addEventListener?

In my application, there are several buttons which trigger my function loadObj(a). This function mainly loads the corresponding 3D object using the Three.js library.
When I choose a object and click the corresponding button, a set of three extra buttons appear which allow me to load three variations of the selected object. The code below already works for this scenario using addEventListener.
My problem arises when I select a different object, which triggers the code below again. Then, if I click one of the extra buttons for the newly selected object, it loads the correct object, but it also loads the previous one. If I choose a third object, if I click one of the extra buttons, it will not load just the corresponding object, but the previous two as well.
I have read that addEventListener works in a cumulative manner, where the functions just keep being added up. So, everytime it runs the loop below, it adds a new loadObj with the path of the new model to any other previous loadObj.
Is there any way to overwrite a function inside addEventListener? I need the previous loadObj to be removed from addEventListener before adding the new one.
//Solve the scope/closure problem to able to call loadDress inside the "for" loop below
function delegate(a) {
return function(){
loadObj(a)
}
}
for(var item in paths){
document.getElementById("size" + item).style.display = "inline-block";
document.getElementById("size" + item).addEventListener("click", delegate(paths[item]), false);
}
If you run that loop every time you click the button, it's adding an event listener on every run. That's why you keep getting more and more items each time--you keep adding more functions.
Instead of trying to dynamically add new event listeners on dynamically added buttons, you can delegate your event listening to a parent element that is a direct ancestor of all of the buttons. Then you have a single event listener that works for all of your buttons without any extra effort. You just check to make sure a click is from the right type of element and then you can get any relevant information directly from that element (via data- or other attributes on the event object target).

Same ID's in jQuery Tabs

I am using the jQuery Tabs library in a small application. The page has 5 tabs and the content for each page is loaded using Ajax. The problem is, once I load a tab, it remains in the browsers memory (and so do its HTML elements). So if I use lets say a DIV element with the same ID as a previously loaded tab, all JS function related to that ID try to interact with the old tab.
IN other words, lets say I have a page with 2 tabs, "Traffic Data1", "Traffic Data2". Now first, I click on the Traffic Data1 tab which makes the ajax call and loads the page just fine. This page, has 2 date input fields, id for the first field is "dateFrom" and the other field is "dateTo". Next to that is a "Go" button. Upon clicking the button, a JS function shows an alert box with the values in each of the input fields.
Now, I click on the "Traffic Data2" tab. The contents of the page are very different, but it has the identical input fields, 2 for dates (with same IDs) and Go Button. When I press the Go button on this page, I see the alert box with values form the previous tab.
So my question is, Is there a way to unload the previous tab? Or is the only alternative to use elements with unique divs (even though the pages are complete separate).
Thanks
You cannot have multiple element with the same ID. When you find an element by ID the first one found is always returned because it is expected that IDs will be unique.
Leave the name attributes for the input elements the same but change their IDs to be unique.
You can select an element by its name attribute like this: $('[name="foobar"]')
Update
In the docs for jQuery UI Tabs there is an option called cache that when set to false should remove the old tabs from the DOM after you navigate away from them:
Whether or not to cache remote tabs content, e.g. load only once or
with every click. Cached content is being lazy loaded, e.g once and
only once for the first click. Note that to prevent the actual Ajax
requests from being cached by the browser you need to provide an extra
cache: false flag to ajaxOptions.
Source: http://jqueryui.com/demos/tabs/
You are looking for jQuery Live.
Description: Attach an event handler for all elements which match the current selector, now and in the future.
If you use it jQuery will magically auto-update to match your new elements as they appear/disapear.
// code sample
$("a.offsite").live("click", function(){ alert("Goodbye!"); });
Since the tabs click event reloads your form and assuming you're using divs to contain the ajax-loaded content, add .click(function () { $(this).children('div').children.remove(); }) to your tabs() declaration.
That should remove the div content and any event handlers that are bound to it.
If you can pass a context to the jquery functions, you could make your calls relative to currently selected tab...
$("#someDuplicatedId", activeTab).doStuff();
Or if caching the content is not important, go with Jasper's answer.

How to handle Android's Back Button click in a single HTML page webapp using PhoneGap?

I read from the documentation that we can handle the back button click using the following code:
document.addEventListener("backbutton", backKeyDown, true);
function backKeyDown() {
// Call my back key code here.
alert('go back!');
}
My concern is that I have a single HTML5 web page in which I have multiple div tags which I animate using jQuery as per the navigation option selected by the user from the menu options.
How can I, in this single page webapp, handle the back button click using PhoneGap and show the user the previously animated div. Clicking on the back button again would again take him to the previous div of the current previous div :-)
Thanks.
I solved the problem by creating a global array variable as
var myStack = new Array();
Then whenever I clicked on the div tag, I inserted the function prototype along with the arguments inside the myStack variable. For eg:
myStack.push(\"myfunction(args1, args2);\");
Then, using the code which I posted in my question, inside the BackButton handler, I wrote the following code:
var divToShow = myStack.pop();
eval(divToShow);
Hope this helps others.
I did an implementation in a similarly structured phonegap app. My situation was a bit more complex because I was loading in html as well as external data via ajax (rather than just unhiding divs). I created a global array called history which I used to keep track of current position as well as previous positions (position here being the most recent ajax function called, so the array was actually storing function names as text). The right sequence and combination of .pop and .push array methods got me a fully functioning js back button that scaled nicely and handled any kind of back and forth navigation I could think of.
I will just post my overall idea of handling this situation. Hope you can improvise and change it to suit your needs.
Have a global variable to remember the current div id that is
visible. For example, when a menu item x is clicked, set this global
variable to the div id that is currently visible (before showing the next div corresponding to menu item x).
When the back button is pressed, use the global variable's value to identify the previous div. Hide the current div and show the previous one.

Categories