[WINJS][UWP] GoBack Button on TitleBar - javascript

I'm trying to create a GoBack button in Title Bar for WINJS application with Visual Studios. I tried lot of codes, but can't get it to work.
Some of codes show's only the GoBack button, but does actually no Action, i'm beginner with WINJS/JS, and can't get a code to work.
I tried with Examples, but can't get a right code from examples, because it's not a full code for Example /* Your success and error handlers */, i don't know what i actually should put into it. Can someone help?
I Tried with this code:
(function () {
"use strict";
var currentview = Windows.UI.Core.SystemNavigationManager.getForCurrentView();
currentview.appViewBackButtonVisibility = Windows.UI.Core.AppViewBackButtonVisibility.visible;
function onBackRequested(eventArgs) {
WinJS.Navigation.back(1).done( /* Your success and error handlers */);
}
})();
Thanks.
EDIT
Ahm, how can i register a function as in Comments someone said? :x
"Make sure you register "onBackRequested" function to currentView.backrequested event."
And Thanks for Reply's
EDIT 2
Solved it, Thanks for Reply's

because it's not a full code for Example /* Your success and error handlers */, i don't know what i actually should put into it.
You can add success function implementation and error function implementation inside ".done()", but in your case, it is not necessary.
To make the back button functions,you can do follows:
Make sure you register "onBackRequested" function to currentView.backrequested event.
WinJS application should be a single page application, and navigation happens between PageControls or HtmlControls. Win8.1 Navigation Template offers a good example of Navigation, which can also be applied to the Windows 10 UWP. You can use it in your project.
I've made a basic navigation example that you can refer to: NavigationSample

Related

Cypress does not always executes click on element

I am automating Google Calculator.
And from time to time Cypress is not able to execute click on button.
The tests click on buttons (0 to 9 ) and do some simple math operations.
And in 30% chance it can not click on element and the test will fail.
I also recorded a video when issue appears.
Video here
My Project is located here:
https://github.com/afiliptsov/test-project
To run the test run : "npm run test:e2e:functional"
I tried to use different locator. Initially i was using just ID ex(#cwbt15 ) but after i made more specific locator ( #cwbt15 > .cwbtpl > .cwbts) and still having same issue.
Does anyone knows why it happens and how to avoid such behavior?
The project structure is :
cypress/PageObject.js - place where all elements declared.
cypress/support/commands.js - place where function click created and
verification of value getting updated.
cypress/integration/functional/delete.spec.js - test which was on the
video
2022 here and tested with cypress version: "6.x.x" until "10.x.x"
You could use { force: true } like:
cy.get("YOUR_SELECTOR").click({ force: true });
but this might not solve it ! The problem might be more complex, that's why check below
My solution:
cy.get("YOUR_SELECTOR").trigger("click");
Explanation:
In my case, I needed to watch a bit deeper what's going on. I started by pin the click action like this:
Then watch the console, and you should see something like:
Now click on line Mouse Events, it should display a table:
So basically, when Cypress executes the click function, it triggers all those events but somehow my component behave the way that it is detached the moment where click event is triggered.
So I just simplified the click by doing:
cy.get("YOUR_SELECTOR").trigger("click");
And it worked 🎉
Hope this will fix your issue or at least help you debug and understand what's wrong.
For me this code worked:
Inside your click methods add : { force: true } It will make force click.
Also add: cy.wait(150) to beforeEach or before click where your test fails.
It is just workaround not a solution.
Link to Cypress Issue
Also i saw this alternative:
cy.get('#query-btn').invoke('width').should('be.gt', 0)
cy.get('#query-btn').invoke('width').should('be. greaterThan', 0)
But it didnt work out for me. Maybe will be usefull for someone!
https://github.com/cypress-io/cypress/issues/2928 helped me.
cy.get('[data-qa="select_workers-list"]'.contains('+ New Worker').trigger('mouseover').click();
Whoever finds this problem, the official way of handling it is described here: https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/
TLDR:
What #jpvantuyl said, cypress clicks the button before the onclick event is there.
The lib cypress-pipe will add a .pipe method that if followed by .should will retry a function until the condition is true or it times out.
Example:
cy
.get(numbers.result.idLocator)
.pipe($el => $el.click()) // try this
.pipe(
// next line will make assertions on the element returned by this pipe
() => cy.get(calculatorScreen.resultOutput.idLocator)
)
.should("contain", "0"); // until this happens or times out
This could be because the application is attaching behaviors to the button via JavaScript. When that script takes a long time to execute it allows Cypress to click the button before the OnClick event is there.
See: https://www.cypress.io/blog/2018/02/05/when-can-the-test-start/
Cypress recommends tracking when the underlying JS is in place with something like:
function waitForAppStart() {
// keeps rechecking "appHasStarted" variable
return new Cypress.Promise((resolve, reject) => {
const isReady = () => {
if (appHasStarted) {
return resolve()
}
setTimeout(isReady, 0)
}
isReady()
})
}
it('greets', () => {
cy.visit('app.html', {
onBeforeLoad: spyOnAddEventListener
}).then(waitForAppStart)
// all other assertion will run only when
// the application has started
cy.get('#name').type('Cypress{enter}')
cy.contains('#answer', 'Cypress')
})
Something I just learned from a colleague after none of the above worked for me and after hours of searching. Just blew my mind. Just add another .click()...
before:
cy.contains('some string').click();
In the left Cypress menu click on the action and you'll see the indicator that it clicks the correct part, but nothing happens. Do it manual in the browser and it works.
Fix:
cy.contains('some string').click().click();
and all of the sudden the string is clicked and test is moving on to the next page
In my case I had to make sure the button is visible(or not disabled), then mouseover, then click:
cy.contains(/activate/i)
.should('be.visible')
.trigger('mouseover')
.click({ force: true });
PS. /***/i means ignore letter case.
I don't know why, but for me this worked:
cy.get('[role="button"][aria-haspopup="listbox"]').trigger('mouseover').wait(1000).click().click({force:true});
I found that my button's event listeners were loaded but the button was not receiving the focus it needed. It was definitely clickable. I tried using the cypress-pipe package but to no avail. So, instead of invoking .click() on it 2 or more times, I ensured it was first set in focus prior to being clicked. This fixed it for me.
cy.get('button').focus().click()
FWIW: I was having problems submitting/navigating after a Google Places address selection. I believe my component wasn't re-rendering post-address selection.
To solve my issue, after address selection, I selected a random text element, clicked on it (no-op) and then clicked on my continue button and it worked fine.
I switched my app from being rendered as SPA to using SSR (basically removing ssr: false from my svelte.config) which started to fail my Cypress tests. Reverting fixed it for my test setup.

Moving from page to page creates errors (duplicates?)

I'm trying to use the pushPage() function of the OnsenUI 2 (rc15 as of now). Alongside the OnsenUI, I'm using jQuery 3.
Here is my function that upon clicking certain elements should push a page:
$(".tile_handler").on("click", ".imalink", function () {
var link = $(this).data().href;
if(link != null){
document.querySelector("#myNavigator").pushPage(link, { animation: "slide-ios" });
}
})
When I push the page for the first time, it works fine. I use the iOS back button to return. Then I click it again and I get this error (and increasingly more as I repeat the process):
[index.js:450] Uncaught (in promise) pushPage is already running.
Here is another function that is supposed to load splitter pages:
$(".splitter_item").click(function () {
var address = $(this).data('address');
$('#content')[0].load(address).then(menu.close.bind($('#menu')[0]));
})
When I switch between two pages via Splitter it starts throwing this ( and more every time I switch between pages)
[undefined:1] Uncaught (in promise) Splitter side is locked.
What I assume is happening is that I load a page, leave it and when I access it again, it loads the page again. However that doesn't seem to be the behavior shown in OnsenUI examples such as this:
document.addEventListener('init', function(event) {
var page = event.target;
if (page.id === 'page1') {
page.querySelector('#push-button').onclick = function() {
document.querySelector('#myNavigator').pushPage('page2.html', {data: {title: 'Page 2'}});
};
} else if (page.id === 'page2') {
page.querySelector('ons-toolbar .center').innerHTML = page.data.title;
}
});
There is the popPage() function which should delete previously loaded page and would prevent this. But the references don't use it, so I assume I'm doing something wrong. But I don't know what.
UPDATE:
I managed to reproduce both problems in CodePen. Here is the Splitter error and here is the pushPage() one. It seems like the pushPage() one is a problem with my function as it adds a pushPage() request every time I click it, not sure why though.
Both errors only seem to happen in Ripple emulator (via VS2015). I don't seem to be able to reproduce them in Android Emulator (but the $(".tile_handler").on("click", ".imalink", function () { code fires incorreclty multiple times anyway). I'm testing this further.
Basically each time you push a page, that page fires an init event. However Onsen still keeps the initial page in the dom.
Navigator example (the same logic applies to the splitter one):
<ons-navigator>
<ons-page id="dashboard">
<div class="imalink" data-href="request_list.html"></div>
</ons-page>
</ons-navigator>
You have an init event for dashboard. Then you click the tile and go to another page.
Then request_list fires its own init event. However our initial page is still in the dom.
<ons-navigator>
<ons-page id="dashboard" style="display: none">
<div class="imalink" data-href="request_list.html"></div>
</ons-page>
<ons-page id="request_list">
...
</ons-page>
</ons-navigator>
You have something like this. However the following is called a second time:
$(".tile_handler").on("click", ".imalink", function () {
...
})
Which adds the listeners once more. $el.on("click") like an alias of addEventListener, meaning you are adding more and more listeners.
So whenever you navigate you keep adding them because the initial page was never removed from the dom.
Alternative solutions:
Use only the current page (e.target)
$('selector') // instead of this
$(e.target).find('selector') // use this
That way you limit to only finding elements within the page which you just created.
Enable the handlers from the start.
Since you are using jQuery there is actually a simpler way to do the things without relying on the init event.
Just do this outside of any init handler:
$(document).on("click", ".tile_handler .imalink", function () { ... })
This actually means that the handler is attached to the document itself and the handler will be called only when the target is .tile_handler .imalink - so it works with any future imalinks which you create.
This may not be the most efficient approach, but is definitely one of the simplest.
Both errors which you mention are actually a safe measure from you pushing or doing some action twice by mistake if you double click a button/link for example.
They appear when you try to make an action while an animation is running. As you can see in the examples generally there is no problem to push a page twice or more, as long as you start the second push after the first one is finished.
Here are demos with your exact code for both the splitter and navigator.
So the error does not come from the code which you provided, its someplace elsewhere.
The only thing I can come up with is that the behaviour which you mentioned would be seen if for some reason the popPage method failed to finish correctly. Maybe if you provide us with your own codepen where the issue can be reproduced we could debug it further.
An alternative, though highly NOT recommended would be to force the state before you do your action. This however would not be solving the problem, rather only masking it. And of course as with all hacks - it may break in future versions.
myNavigator._isRunning = false;
UPDATE:
Here are the two updated pens which you gave in the comments:
https://codepen.io/IliaSky/pen/YWOOkW?editors=1010
https://codepen.io/IliaSky/pen/QEVVGm?editors=1010
Basically you were adding the handlers on init event, which is fired whenever a page is added. so with your logic you are adding more and more handlers with each page. Just make sure you add them only once and you will be fine.
Add things like:
if (e.target.id == 'pagename') ...
or simply
$(document).on("init", '#dashboard_page', function(){ ... }
Take a look at .one() from jQuery - the event handler will only execute once per element in order to prevent the error: Uncaught (in promise) pushPage is already running
$(".tile_handler").one("click", ".imalink", function () {
var link = $(this).data().href;
if(link != null){
document.querySelector("#myNavigator").pushPage(link, { animation: "slide-ios" });
}})

Javascript/Jquery How to compare ID's and if true, not call a function

I have a Javascript imported a snow.js file that displays "Snow falling" across the screen for when it's winter. But If I choose a summer theme on the same page it will still display the Snow falling.
<script src="js/snow.js" type="text/javascript"><script>
Is their a way to create a Javascript code so if i click on a summer theme it will remove/comment the imported file and add/re-move commenting on the imported file when I click on a winter theme?
Edit:
I am using snowstorm.JS plugin realized I can call a function "snowStorm.toggleSnow()" via script. But I need to adjust it, so if they click on my css button "Summer" whilst on the theme summer it will do nothing.
I created this Jquery/JS code but it doesn't work. I believe it's the brackets but not sure. It should solve the problem.
Update:
I got it working, so If the user clicks a button it will "Toggle" the snowstorm effect on and off.
$("#Summer").click(function(){
snowStorm.toggleSnow()
});
$("#Winter").click(function(){
snowStorm.toggleSnow()
});
Is there a way of introducing if loops, so if the user clicks on the same button, eg: ID "Summer" whilst on the same ID/CSS "Summer" it will not toggle the snowstorm?
Use JS or jQuery to remove the tag.
For example, in jQuery:
$("#summerThemeButton").click(function() {
$("script[src=js/snow.js]").remove();
});
However, as #IgorRaush commented, there's probably a better way to change the theme (probably by a JS API) than to remove the script for it completely.
EDIT
As the comments suggest, it's not so easy to remove a JS file by removing the <script> tag. It is already executing code. The best way is to use the functions that came with it to stop it. Maybe you want to check if there are functions, such as:
var stopSnow = function() { /* ... */ };
var changeTheme = function(newTheme) { /* ... */ };
If there are truly no API functions (if you found an API; if you wrote it yourself just write a function!) then your best bet might be to remove all relevant/global variables and functions:
// for example, if you had a running function `snow()` or a global variable to make it snow:
snow = null;
theme = null;
Sorry there's no better way (I know of) to remove a script.
you can use $.getScript in jQuery to conditionally load the file. See more at http://api.jquery.com/jQuery.getScript/

How to register a function to be run when an update panel request is complete

Library: Bootstrap 3:Collapse.js.
I have tried
$(document).ready(function () {
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandler);
});
function endRequestHandler(sender, args) {
//alert("this should work");
$('#collapseTwo').collapse.in();
But it throws Uncaught TypeError: undefined is not a function
The alert instead works no problem.
I thought JQuery was undefined but the page where this code is inherits all the appropriate scripts from a masterpage, so that's not the problem.
So, following this advice I went on to trying
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(endRequestHandler);
But I made no progress.
I've also tried to use the body tag, but still no joy.
Can please somebody tell me what I'm doing wrong?
Thanks.
Bootstrap and its libraries work mainly with classes and data-bindings.
There is no in() function for the collapse.js of bootstrap. If you want to reset the collapsable to be to collapse in you need to remove the class
$('#collapseTwo').removeClass('in');
This will make it reset.
If you would like the animation too you can trigger this with jquery by simulating a click (or how every your app triggers this collapse to show)
$(<selector for your button>).trigger('click')

How do we set an onExpand event in a cfLayout accordion

We're using CFLayout to create a tab structure in our web application. After creation of that layout we call this function:
mytabs = ColdFusion.Layout.getTabLayout("#attributes.cflayoutName#");
mytabs.on('tabchange',
function(tablayout,tab) {
var tabtitle = tab.title;
alert(tabtitle); // Actual code does various useful 'stuff' here.
}
);
That piece of code works very well, and the alert will show each time the user clicks on a tab.
The problem is that we are now trying to do the same thing with a CFLayout type of "accordion", and I cannot get an event to fire when the user switches which accordion pane they are looking at. We've tried leaving the above as is, as well as changing the "tabchange" attribute to "expand", "beforeexpand", "activate", and "collapse".
For this testing I'm using the following simple JS function to avoid issues arising from the JS within the onchange event:
mytabs = ColdFusion.Layout.getAccordionLayout("#attributes.cflayoutName#");
mytabs.on('expand',
function(tablayout,tab) {
console.log('test');
}
);
We do not receive any errors. Nothing is logged to the console at all. I've tried replacing the console.log to an alert to rule out any problems with that line.
I found that the Ext library documentation to be very helpful with finding a solution to this problem: here.
The Ext library has a getComponent method that allows you to reference the accordion layout panel that you are trying to add the expand event to. Once you have this, you can use the "on" method you are using above to assign the expand event to each panel individually.
for (x=1; x<accordionLayoutArray.length; x++) {
mytabs.getComponent(accordionPanelName).on('expand',
function(tab) { ... });
}
This became too long for a comment so adding as an answer
After some Google searches I found what I think are some related posts. It appears as though the accordion in Ext JS does not have the same events as the tab. Instead you need to add a listener in order to catch the expanding.
See this post - in case something happens to that page here is the relevant piece:
You'd need to listen to the expand event of the child panels in the accordion, you could do something like:
Code:
myAccordion.add(myFunc('myTitle'));
function myFunc(title)
{
return new Ext.Panel(
{
title: title,
listeners: { 'expand': {fn: something, scope: foo}}
}
);
}
And I also found another similar post here on SO - see both answers
Once you know that the accordion needs a listener you can find a number of results on Google. Such as How do I attach an event handler to a panel in extJS?
This Google search will give you lots of examples.
Hope that helps.

Categories