How to bind popup user control to view model and how to handle back button? (Windows Phone 8.1 Runtime) - mvvm

I'm working on WP 8.1 runtime application and I'm using Caliburn.Micro. Application follows MVVM pattern. I have an ItemPageView and ItemPageViewModel and data binding works as it should.
I want to add popup (UserControl) over ItemPageView(Page) after I click one item on ItemPage. Popup has only one ScrollViewer containg one Image and I want to do something like this :
<Image x:Name="imageFull"
Source="{Binding _currentItem.ImageURL}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
_currentItem is a property of ItemPageViewModel.
My second problem is related to Back button. I've added this to my code:
void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
Frame frame = Window.Current.Content as Frame;
if (_popUpActive)
{
_popUpActive = false;
_showImagePopUp.Close();
frame.GoForward();
//var lastPage = frame.BackStack.LastOrDefault();
//frame.Navigate(typeof(SingleGuideView));
e.Handled = true;
}
else
{
frame.GoBack();
e.Handled = true;
}
}
After I click on Back button Popup will close, and after that, it will navigate back. Only "solution" to stay on current view is to call frame.GoForward(); .

About the Popup, you can write some Code like the following in you XAML (Keep the Popup in just below the First Grid):
<!-- This is the First Grid -->
<Grid>
<Popup x:Name="myPopup" Width="400">
<ScrollViewer>
<StackPanel>
<Image x:Name="imageFull"
Source="{Binding _currentItem.ImageURL}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</StackPanel>
</ScrollViewer>
</Popup>
</Grid>
You can handle the problem with the Popup by having a Counter for the Hardware Back Button Press. Have a look at the Code Below:
int _popUpCounter = 0, _dummyCounter = 0;
void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
_dummyCounter++;
Frame frame = Window.Current.Content as Frame;
if (_popUpCounter == 0 && _dummyCounter == 1)
{
_popUpCounter = 1;
_popUpActive = false;
_showImagePopUp.Close();
frame.GoForward();
//var lastPage = frame.BackStack.LastOrDefault();
//frame.Navigate(typeof(SingleGuideView));
e.Handled = true;
}
else if (_popUpCounter == 1 && _dummyCounter == 2)
{
_popUpCounter = _dummyCounter = 0;
frame.GoBack();
e.Handled = true;
}
}
This will help you with the problem related to Popup.

Related

How to create close functionality in context menu with Syncfusion ej2

I would like to create a right click context menu on my tab with close tab functionality using Syncfusion ej2. But I can't find any documentation for this particular functionality.
You can use the "removeTab" public method of tab by passing the respective index to close the tabs. We have prepared the sample based on your requirement.
<div>
<ejs-tab id="appTab" showCloseButton="true">
<e-tab-tabitems>
<e-tab-tabitem header="ViewBag.headerTextOne" content="#contentOne"></e-tab-tabitem>
<e-tab-tabitem header="ViewBag.headerTextTwo" content="#contentTwo"></e-tab-tabitem>
<e-tab-tabitem header="ViewBag.headerTextThree" content="#contentThree"></e-tab-tabitem>
</e-tab-tabitems>
</ejs-tab>
<ejs-contextmenu id="contextmenu" target="#appTab" items="ViewBag.menuItems" select="menuClick"></ejs-contextmenu>
</div>
<script>
function menuClick(args) {
if (args.item.text == "Close All") {
var tab = document.getElementById('appTab').ej2_instances[0];
for (i = $('#appTab .e-toolbar-item').length; i >= 0; i--) {
tab.removeTab(i);
}
} else if (args.item.text == "Close This Tab") {
var tab = document.getElementById('appTab').ej2_instances[0];
var activeTab = tab.selectedItem;
tab.removeTab(activeTab);
}
}
</script>
Sample: https://www.syncfusion.com/downloads/support/directtrac/298062/ze/TabComponent673764834
https://ej2.syncfusion.com/documentation/api/tab/#removetab

TVML - Navigate through templates

I´m doing something very wrong, but I´m not very sure of what.
I am trying to create an app which loads a TVML template. From there, you can navigate to a new view (also a template) with information about the selected item. Finally, in this view, you can choose to play the video.
It works until I play the view because it loads but the second screen is on top. I have to "go back" with the menu button to see the video...
Here is my code (simplified of menus and buttons):
application.js
var resourceLoader;
App.onLaunch = function(options) {
var javascriptFiles = [
`${options.BASEURL}/js/ResourceLoader.js`,
`${options.BASEURL}/js/Presenter.js`
];
evaluateScripts(javascriptFiles, function(success) {
if(success) {
resourceLoader = new ResourceLoader(options.BASEURL);
resourceLoader.loadResource(`${options.BASEURL}/templates/Stack.xml.js`, function(resource) {
var doc = Presenter.makeDocument(resource);
doc.addEventListener("select", Presenter.load.bind(Presenter));
Presenter.pushDocument(doc);
});
} else {
var errorDoc = createAlert("Evaluate Scripts Error", "Error attempting to evaluate external JavaScript files.");
navigationDocument.presentModal(errorDoc);
}
});
}
Presenter.js
function getDocument(url) {
var templateXHR = new XMLHttpRequest();
templateXHR.responseType = "document";
templateXHR.addEventListener("load", function() {
pushDoc(templateXHR.responseXML);}, false);
templateXHR.open("GET", url, true);
templateXHR.send();
return templateXHR;
}
function pushDoc(document) {
navigationDocument.pushDocument(document);
}
var Presenter = {
makeDocument: function(resource) {
if (!Presenter.parser) {
Presenter.parser = new DOMParser();
}
var doc = Presenter.parser.parseFromString(resource, "application/xml");
return doc;
},
modalDialogPresenter: function(xml) {
navigationDocument.presentModal(xml);
},
pushDocument: function(xml) {
navigationDocument.pushDocument(xml);
},
load: function(event) {
console.log(event);
var self = this,
ele = event.target,
videoURL = ele.getAttribute("video"),
templateURL = ele.getAttribute("template"),
presentation = ele.getAttribute("presentation");
if(videoURL) {
var player = new Player();
var playlist = new Playlist();
var mediaItem = new MediaItem("video", videoURL);
player.playlist = playlist;
player.playlist.push(mediaItem);
player.present();
}
if(templateURL) {
self.showLoadingIndicator(presentation);
resourceLoader.loadResource(templateURL,
function(resource) {
if (resource) {
var doc = self.makeDocument(resource);
doc.addEventListener("select", self.load.bind(self));
//doc.addEventListener("highlight", self.load.bind(self));
if (self[presentation] instanceof Function) {
self[presentation].call(self, doc, ele);
} else {
self.defaultPresenter.call(self, doc);
}
}
}
);
}
},
showLoadingIndicator: function(presentation) {
if (!this.loadingIndicator) {
this.loadingIndicator = this.makeDocument(this.loadingTemplate);
}
if (!this.loadingIndicatorVisible && presentation != "modalDialogPresenter" && presentation != "menuBarItemPresenter") {
navigationDocument.pushDocument(this.loadingIndicator);
this.loadingIndicatorVisible = true;
}
},
removeLoadingIndicator: function() {
if (this.loadingIndicatorVisible) {
navigationDocument.removeDocument(this.loadingIndicator);
this.loadingIndicatorVisible = false;
}
},
defaultPresenter: function(xml) {
if(this.loadingIndicatorVisible) {
navigationDocument.replaceDocument(xml, this.loadingIndicator);
this.loadingIndicatorVisible = false;
} else {
navigationDocument.pushDocument(xml);
}
},
loadingTemplate: `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<loadingTemplate>
<activityIndicator>
<text>Loading...</text>
</activityIndicator>
</loadingTemplate>
</document>`
}
I also use a ResourceLoader.js file but I think it is not important as it is the one shown in documentation.
When the app launches, I therefore load my first "template" view.
Stack.xml.js
var Template = function() { return `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<stackTemplate>
<collectionList>
<carousel>
<section>
<lockup>
<img src="${this.BASEURL}/images/main_carousel/main_carousel001.png" width="1740" height="500" />
<overlay>
<title>Title</title>
<subtitle>1902</subtitle>
</overlay>
</lockup>
</section>
</carousel>
<shelf>
<header>
<title>Last Added</title>
</header>
<section>
<lockup template="${this.BASEURL}/templates/Product-001.xml.js" presentation="modalDialogPresenter">
<img src="${this.BASEURL}/images/movies/movie001.png" width="332" height="500" />
<title class="scrollTextOnHighlight">My Title</title>
</lockup>
</section>
</shelf>
</collectionList>
</stackTemplate>
</document>`
}
When click on the image, I load my next template using the template parameter. This template is Product-001.xml.js
var Template = function() { return `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<productTemplate theme="light">
<shelf>
<header>
<title>Last Added</title>
</header>
<section>
<lockup video="http://trailers.apple.com/movies/focus_features/9/9-clip_480p.mov">
<img src="${this.BASEURL}/resources/images/movies/movie_520_e2.lcr" width="332" height="500" />
<title class="showAndScrollTextOnHighlight">Title 2</title>
</lockup>
</section>
</shelf>
</productTemplate>
</document>`
}
This is using the video parameter. On the first "screen" everything works, no matter if I try to load a Template or a video. However, the same code does´t seem to work on the second screen.
Could someone help me with this?
I don´t know much about Javascript.
I have seen some posts where people say you must push the pages on the stack like this:
var parser = new DOMParser();
var newPageDocument = parser.parseFromString(NEW_PAGE_XML, 'application/xml');
navigationDocument.pushDocument(newPageDocument);
If this is the solution, I would be very grateful if someone could explain me where does that code need to be. Or how can I implement it correctly if I want multiple screens.
Thank you all very much!
Most likely this happens because you are using presentation="modalDialogPresenter" to load Product-001.xml.js file.
Your video may be staying behind the modal, try to see if you can see it when you press Escape.
Then remove that part and test it again.
"modalDialogPresenter" is geared for alerts.
Hey did you finally get the answer to this. I had a similar issue, my video was playing in the background. I could hear the audio but it was "covered" by the current template. The way I fixed this was somewhat of a hack, but i just simply dismissedModally the current view in the function that plays the video. I have a function in my presenter class that plays the video.I don't see this in your code. I think this is what your referring to. Let me know if this helps.
I ended up doing this in the Presenter file.
It seems to work ok:
if(templateURL) {
self.showLoadingIndicator(presentation);
resourceLoader.loadResource(templateURL,
function(resource) {
if (resource) {
var doc = self.makeDocument(resource);
doc.addEventListener("select", self.load.bind(self));
//doc.addEventListener("highlight", self.load.bind(self));
if (self[presentation] instanceof Function) {
// self[presentation].call(self, doc, ele);
self.defaultPresenter.call(self, doc);
}
/* else { self.defaultPresenter.call(self, doc); }
*/
}
}
);
Hope it helps!

Added navigation button doesn't work first time in Titanium alloy

i added navbutton to navigation and i wrote 'click' function on to it doesn't work first time . actually am adding button to navigation bar on that first click it was not working on second click it works how can i solve this
my xml code is
<Alloy>
<Window id="aboutWin" name="aboutWinName">
<NavigationGroup id="navAbout" platform="ios">
<Window class="container" id="aboutChildWin">
<View id="aboutView">
<ImageView id="logoImg"></ImageView>
<ImageView id='logoWrd'></ImageView>
<Label id="versionLbl"></Label>
</View>
<View id="footView"></View>
</Window>
</NavigationGroup>
</Window>
</Alloy>
and my Js code is
var button = Titanium.UI.createButton({
// title:"Back",
backgroundImage:"/images/MenuList.png",
// top : 4.5,
height : 35,
width : 40,
// left : 4
})
$.aboutChildWin.leftNavButton = button;
button.addEventListener('click',function(){
if(Ti.App.currentAnimateWindow == "About")
{
Ti.App.socialWindow.hide();
Ti.App.menuWindow.show();
$.aboutWin.animate(animateLeft);
Ti.App.currentAnimateWindow = "Menu";
}
else if(Ti.App.currentAnimateWindow == "Menu")
{
$.aboutWin.animate(animateRight);
Ti.App.currentAnimateWindow = "About";
}
})
can any one solve this
i just make small change, insert of adding button to navigation window i add the navbutton to whole window.
code is :
$.aboutWin.leftNavButton = button;
That might sound stupid but did you try to change the order?
var button = Titanium.UI.createButton({
// title:"Back",
backgroundImage:"/images/MenuList.png",
// top : 4.5,
height : 35,
width : 40,
// left : 4
});
button.addEventListener('click',function(){
if(Ti.App.currentAnimateWindow == "About")
{
Ti.App.socialWindow.hide();
Ti.App.menuWindow.show();
$.aboutWin.animate(animateLeft);
Ti.App.currentAnimateWindow = "Menu";
}
else if(Ti.App.currentAnimateWindow == "Menu")
{
$.aboutWin.animate(animateRight);
Ti.App.currentAnimateWindow = "About";
}
};
$.aboutChildWin.leftNavButton = button;
Without using alloy this change makes no difference.

How to bind event to multiple selectmenu change in jquerymobile

I want to refresh my page when I finish choosing the selects in jquerymobile.Now Im using the onchange attribute in tag.here's my code.
<div data-role="fieldcontain" style = "background-color:white;border-bottom:1px solid #ccc">
<label for="select-choice-1" class="select">select specity:</label>
<select name="select-choice-1" id="select-choice-1" data-native-menu = false multiple=true onchange = "selectChange()"></select>
</div>
$("#select-choice-1").empty();
for (var i = 0; i < item.tagClassList.length; i++) {
if (item.tagClassList[i].isSelected) {
$("#select-choice-1").append("<option value="+item.tagClassList[i].id+"checked = true>"+item.tagClassList[i].className+"</option>");
} else {
$("#select-choice-1").append("<option value="+item.tagClassList[i].id+">"+item.tagClassList[i].className+"</option>");
}
if (i == item.tagClassList.length-1) {
$("#select-choice-1").selectmenu("refresh");
};
};
But the selectmenu() event fires whenever select is selected or selected is cancelled.How can I get the event fires when the selectmenu is closed
try binding to blur() like so
$('document').on('blur', '#select-choice-1', function(){
//run your check here
});
this also takes care of older versions of ios which seem to not fire change events on multiple selects.

Catching play event in video on mobile safari

I have an iOS app that contains a lot of local web content. Some of that content is video/audio. I have a click event attached to the video and audio tags that fires an analytics url that I'm going to catch in the UIWebView. The problem is that click event doesn't register. I'm assuming this is because iOS replaces the video with its own special movie player. How do I catch the play event so I can do something with it. Here's my jQuery code for the click event.
function videoClick() {
$("video").click(function () {
alert("here");
//document.location = "ignoretap:///";
var videoTitle = $(this).attr("data-mediatitle");
var videoSrc = $(this).children("source").attr("src");
if (videoTitle != null && videoTitle.length > 0) {
document.location = "analytics:///" + "page" + videoTitle;
}
else {
document.location = "analytics:///" + "page" + videoSrc;
}
});
}
Here's my html for the video
<video width="100%" controls="controls" data-mediatitle="testing">
<source src="StoryOfIyal.mp4" type="video/mp4" poster="IyalVideo.htm-iyalvideoscreenshot_lg.jpg"></source>
Your Browser does not support the video tag
</video>
Figured it out. You have to bind to the "play" event in jQuery, not the click event. Here's the updated function.
function videoClick() {
$("video").bind('play', function () {
alert("here");
//document.location = "ignoretap:///";
var videoTitle = $(this).attr("data-mediatitle");
var videoSrc = $(this).children("source").attr("src");
if (videoTitle != null && videoTitle.length > 0) {
document.location = "analytics:///" + "page" + videoTitle;
}
else {
document.location = "analytics:///" + "page" + videoSrc;
}
});
}