How to use intern leadfoot waitForDeletedByXpath function? - javascript

On what scenario can i use intern's leadfoot waitForDeletedByXpath function? From the documentation, what I understood is this method waits for the element to become invisible in Page. But while implementing it doesn't seem so. The scenerio i'm using this is as follows:
There is a page in my application where i can search for data with some predefined arguments. After clicking on search button the loading icon appears on the page until the data is loaded in the datagrid and the loading icon disappears after the data is loaded . so I'm trying to use this function to wait until the loading icon disappears from the page so that i can read the data in datagrid without having any issue but it doesn't seems to work that way.
Can someone please throw some light on how this function works and point me towards the right direction to achieve what i'm trying to do.
thanks

I believe what's happening here is a slight misinterpretation of what the waitForDeletedByXPath method does.
What the documentation for this method says is:
"Waits for all elements inside this element matching the given name attribute to be destroyed."
When your loading icon disappears it is most likely still part of the DOM, albeit it is just set to invisible. This method expects the element to no longer be part of the DOM at all.
What you need to do, from my experience, is set up your own "wait for element to be invisible" method for your loading icon.
For example:
return this.remote
.then(function () {
const waitForLoadingIconNotDisplayed = function (remoteSession) {
return remoteSession
.findByCssSelector('your_loading_icon_css_selector')
.isDisplayed()
.then(function (isDisplayed) {
if (isDisplayed) {
return waitForLoadingIconNotDisplayed(remoteSession);
}
return true;
});
};
return Promise.all([waitForLoadingIconNotDisplayed(this.parent)]);
})
This will loop until the condition is met that your loading icon is no longer set as displayed in the UI using the Promise.all() call.
Hope this helps steer you along the right path!

Related

Changing an object properties then calling a function inside a custom function with javascript

Title is probably a little messy. Basically what I'm trying to do is to create a custom function that will modify an object properties, then return that object, and then call a function.
A little background on what I'm doing : Trying my best with the Zendesk API to use a web widget on my webpage. Basically this web widget is configured to be a HelpCenter on startup, which then shows a button for either live chat or email, depending on the state. The main property in question here is called 'suppress' which disables one of the widget pages (chat, email & helpCenter). And my goal is to make that custom function 'suppress' 2 of the 3 widget pages so it only shows one. Then a API func called zE.activate() would open up the widget.
I know this is a lot of text, let me show you the code I've got so far :
<script>
function setChatPopOutProps(window) {
window.zESettings = {
webWidget: {
contactForm: {
suppress: true
},
helpCenter: {
suppress: true
}
}
};
return window.zESettings;
};
function chatPopOut() {
setChatPopOutProps(window);
zE.activate();
};
</script>
Now when I click on the button that has chatPopOut() assigned, the zE.activate() works since it opens up the widget, but basically the setChatPopOutProps(window) didn't seem to work.
I also tried the following :
Not returning window or window.zESettings
Putting everything under a single function by putting zE.activate() at the end of zESettings or just after the return window or window.zESettings
If you need to see the widget in action to have an idea, you can see it right here. Click on the green button on the bottom right, type anything, and you'll see the contact form button pop up. This button changes for a chat button when a live chat agent is available.
Now I know this is something that I should normally work out with Zendesk directly, which I tried, but they told me that there's nothing that can do what I'm trying to accomplish, but I really feel like this has something to do with the way I'm doing things in javascript and not the way the API is built..
Does anyone have an idea ? I would really appreciate it.
P.S. This is my 2nd post, so I apologize in advance for mistakes I probably made in this question.
Sadly, it turns out that what you are trying to accomplish just isn't possible. As the zE.settings get applied when the widget is first initialized, so there is no way to dynamically alter the widget settings without doing an action such as refreshing the page and re-initializing the widget. As far I can see from your code, I dont think you want to refresh the page everytime, and reinitialize the widget just to apply those settings that you listed above.

How to call a Greasemonkey function when a JavaScript link is clicked

So I recently started working on Greasemonkey scripts without much prior experience in JavaScript. It was going fine until I hit this roadbloack.
I'm writing a script for a page that has a small table of information. If a link at the bottom is clicked, the table expands fully in the page to display all information. I need to call a function in Greasemonkey when this happens, however, the link doesn't appear to have an ID or anything I can actually reference to watch it. It's simply this:
When it's clicked, the table expands and it then shows as true. I initially used the following to expand the table upon loading the page, but that broke several things:
window.location.href = ('javascript: expandFullTable(false)');
I've attempted using "click", "onclick", and even "mouseover" to have Greasemonkey detect when it's pressed but nothing seems to work. From what I can tell it's simply a link that calls a function, but after some significant searching I wasn't able to find out anything about how to reference it in my script. I'm sure it's incredibly simple, but it's frustrated me to no end.
You can hijack the function like this:
var oldExpandFullTable = unsafeWindow.expandFullTable;
unsafeWindow.expandFullTable = function() {
// Do something
alert("You clicked on that thing!");
// Call the original function
oldExpandFullTable.apply(this, arguments);
};
But since you tagged this jquery this should let you retrieve the link:
var link = $("a[href^=\"javascript: expandFullTable\"]);
It should work if jQuery is injected into your script with #require. If it's already in the page, you can add this before to access it: var $ = unsafeWindow.jQuery;.
And by the way, perhaps you should learn more about unsafeWindow to avoid security holes.

Programmatically change first page jQuery Mobile shows

My goal is to show a different first page depending on whether the user is logged in or not. The login check happens using a synchronous Ajax call, the outcome of which decides whether to show a login dialog or the first user page.
The normal way to do this would be to set $.mobile.autoInitialize = false and then later on initialize programmatically, as described in the answer to this question. For some reason this won't work, instead another page gets loaded every single time.
I decided to give up on this way and try out a different parcour. I now use a placeholder, empty startup page that should be shown for as long as the login check takes. After the login check it should automatically change. This is done by calling a function that performs the ajax call needed for authentication on the pagechange event that introduces this startup page. The function takes care of changing to the outcome page as well.
The trick is that it doesn't quite do that.. Instead it shows the correct page for just a short time, then changes back to the placeholder. Calling preventDefault in pagechange didn't prevent this, as described in the tutorial on dynamic pages. Adding a timer fixed this, leading me to think that the placeholder wasn't quite finished when pageshow got fired (as per this page on page events), or some side-effect of the initial page load still lingered.
I'm really clueless as to how to fix this seemingly trivial, yet burdensome problem. What causes this extra change back to the initial page? Also, if my approach to intercepting the initial page load is wrong, what would be the correct approach instead?
I use jQuery Mobile 1.4.0 and jQuery 1.10.2 (1.8.3 before).
EDIT: Below is the code to my last try before I posted the question here. It does not work: preventDefault does not prevent the transition to the placeholder page.
$(document).on("pagebeforechange", function(e, data) {
if (typeof(data.options.fromPage) === "undefined" && data.toPage[0].id === "startup") {
e.preventDefault();
initLogin();
}
});
function initLogin() {
// ... Login logic
if (!loggedIn) // Pseudo
$('body').pagecontainer("change", "#login", {});
}
If you're using a Multi-page model, you can prevent showing any page on pagebeforechange event. This event fires twice for each page, once for the page which is about to be hidden and once for the page which is about to be shown; however, no changes is commenced in this stage.
It collects data from both pages and pass them to change page function. The collected data is represented as a second argument object, that can be retrieved once the event is triggered.
What you need from this object is two properties, .toPage and .options.fromPage. Based on these properties values, you decide whether to show first page or immediately move to another one.
var logged = false; /* for demo */
$(document).on("pagebeforechange", function (e, data) {
if (!logged && data.toPage[0].id == "homePage" && typeof data.options.fromPage == "undefined") {
/* immediately show login dialig */
$.mobile.pageContainer.pagecontainer("change", "#loginDialog", {
transition: "flip"
});
e.preventDefault(); /* this will stop showing first page */
}
});
data.toPage[0].id value is first page in DOM id.
data.options.fromPage should be undefined as it shouldn't be redirected from another page within the same webapp.
Demo
I'm undergoing the same problem as the one described by #RubenVereecken, that is, a coming back to the initial page once the cange to my second page has completed. In fact, he posed the question "What causes this extra change back to the initial page?" and it hasn't been replied yet.
Unfortunately, I don't know the reason since I haven't found how the page-event order works in JQM-1.4.2 yet, but fortunately, the workaround suggested by #Omar is working for me.
It's not exactly the same code but the general idea works at the time of preventing a coming back to the initial page. My code is as follows:
$(document).on("pagebeforechange", function(event, data) {
if ( typeof (data.toPage) == "string") {
if (data.toPage.indexOf("#") == -1 && typeof (data.options.fromPage[0].id) == string") {
event.preventDefault();
}
}});
The condition data.toPage.indexOf("#") == -1 is because I checked that all the undesired coming-backs to the initial page were happening when the property '.toPage' was set to something like [http://localhost/.../index.html].

javascript history.back losses the search result

Page A:
$(document).ready(function () {
bindData();
});
function bindData() {
$('#searchbtn').bind('click', function () { SearchResult(); });
}
function SearchResult() {
ajax call...
}
Page A HTML:
<input type="button" id="searchbtn" />
Page B Details---> this page comes after selecting a specific search result from page A search list
Back<br />
Now when I go back to the Page A I can see my search criteria's as they were selected but the result Div is gone. What I am trying to do is I want the search list to stay when the Page comes back.
I think what I can do here is some how call the searchbtn click event again when the page comes back so the list will come-up again. Can anyone tell me how to fire the searchbtn click event only when the page comes back from Page B. or point me in the right way of doing this..
Thanks
The Browser Back button has long been problematic with AJAX. There are scripts, workarounds, and techniques out there (depending on the framework that you want to use).
Since it appears that you are using jQuery (based on your posted JavaScript syntax), here is a link to another Stackoverflow post regarding back button jQuery plugins.
history.back() will return you to the last URL visited, meaning that any ajax calls made during the user's visit will not be automatically repeated. Your browser may automatically restore your form selections, but the SearchResults() function is only called by a click event, not a selection event.
You can bind URLs to ajax states using a framework like sammy.js. That way, history.back() would take you to a URL associated with SearchResults().
function bindData() {
var chkinput1 = $("input:checkbox[name=x]:checked").length;
var chkinput2 = $("input:checkbox[name=y]:checked").length;
if (chkinput1 > 0 && chkinput2 > 0) {
SearchResult();
}
$('#searchbtn').bind('click', function () { SearchResult(); });
}
I know this is the worst way to achieve this result but I think instead of using any other plugins to add complexity we will go with this for now. If anyone else is looking for the same question let me tell you again this is not the best practice as on returning back to the history we are calling the search result again depending upon the cached input selection of checkboxes and generating the whole ajax call again to display the list. On the first request I am caching the list and setting sliding expiration so its not taking anytime to comeback and so everyone lives happily.

loadmask in sencha touch2

I want apply load-mask in view page. while launching the application, some view pages are taking time to load data later it will display, so if its taking time to load in that time i want show load-mask to users with some messages like "loading....". from some sample i have applied load-mask, but it is shows that message every time whenever i hit that page. this is bad way because here setting time. i need apply load-mask like this if don't have data it should show the load-mask to the user, until page getting the data. please any one help me. how to achieve this one
My code is here: at controller level i am taking the id of load-mask and setting the property as shown below code
onCompanyPageLoad: function () {
var loader = Ext.getCmp('mask');
loader.setMessage("Loading...");
loader.setIndicator(true);
loader.setTransparent(false);
loader.show();
setTimeout(function () {
loader.hide();
}, 1000);
}
The answer of user978790 is formal way to show and hide a loading mask in Sencha Touch 2.
If you can't make it work, it's very likely that you're doing something like:
Ext.Viewport.setMasked({xtype:'loadmask',message:'your custom loadmask'});
... then do something here
Ext.Viewport.setMasked(false);
Note that Javascript is asynchronous, so it does NOT make sure that the code lines are run in above order. Then there is a possibily that Sencha Touch initializes your loading mask and destroys it right then. In order to use loading mask correctly:
Initialize a loading mask as above.
Put the Ext.Viewport.setMasked(false); in special functions which are ensured to be launched after loading mask initialization, eg. event handler, or success function of your JSONP/AJAX request.
I do it the following way:
Ext.Viewport.setMasked({xtype:'loadmask',message:'your custom loadmask'});
Then you can use
Ext.Viewport.setMasked(false);
To stop showing a loading mask
This also works on components if you only want to show a mask on part of a view
Just remove all this.I have nice idea how to use loader.First on main page html just add loader
<div id="loader"></div>//add id#loader with background loading image
after your page loads just add on contoller Ext.get('loader').destroy();//when you page full load then it will load your loading div

Categories