Attaching event handlers for dynamically created jQuery Mobile pages - jquery-mobile

In my jQuery Mobile application, I am creating some dynamic pages.Here is the code
function createPages()
{
$header = "<header data-role='header'><h1>Dynamically created pages</h1></header>";
$content = "<div data-role='content' class='content'><p>This is a dynamically generated page</p></div>";
$footer = "<div data-role='footer'><h1>Audimax</h1></footer>";
for($i=1;$i<=5;$i++)
{
$section= "<section id='"+"#fav"+$i+"' data-role='page' data-url='"+"fav"+$i+"' class='dynamic'>";
$new_page = $($section+$header+$content+$footer+"</section>");
$new_page.appendTo($.mobile.pageContainer);
}
}
The pages are being created properly and being added to the DOM and I can navigate to them. The problem is that I simply can,t attach any event handlers to the dynamic pages.I am using ids of the dynamic pages with jquery "live" but to no avail.Any help is greatly appreciated.

Why not bind the event handlers when you add the new pseudo-page to the DOM?
function pageShowFunction () {
console.log(this.id + ' has triggered the `pageShow` event!');
}
function createPages()
{
$header = "...";
$content = "...";
$footer = "...";
for($i=1;$i<=5;$i++)
{
$section= "<section id='"+"#fav"+$i+"' data-role='page' data-url='"+"fav"+$i+"' class='dynamic'>";
$new_page = $($section+$header+$content+$footer+"</section>").bind('pageshow', pageShowFunction);
$new_page.appendTo($.mobile.pageContainer);
}
}
It's normally better to bind directly to elements rather than delegating the event handling.
P.S. You didn't post your event binding code so I can't give any specific comments on that code, perhaps you can update your question with that code if this doesn't fix your issue.

Upgrade the jquery core to 1.7.1 from
http://jquery.com/download/
and then
$(selector).live( eventName, function(){} );
Can be replaced with the following on signature
$(document).on( eventName, selector, function(){} );
It then works for dynamic elements.

Related

How to have a handler for pagination complete

This API from angular-ui-grid is provided for pagination
gridApi.pagination.on.paginationChanged($scope, vm.updateHeaderCheckBoxState)
vm.updateHeaderCheckBoxState = function() {
const isAllVisibleRowsSubscribed = vm.isAllSelected(vm.gridOptions.titan.gridApi.grid.getVisibleRows());
if (isAllVisibleRowsSubscribed) {
$scope.headerCheckBoxSelected = true;
} else {
$scope.headerCheckBoxSelected = false;
}
};
The registered handler using above API is called before the start of pagination. Do we have any alternative to handle after pagination ?
After investigating ui-grid Pagination, we do not have a handler for after pagination. The current event is used to load the data in case external pagination is enabled. So, the solution i worked out is remove ui-grid-selection directive, added a new column for checkboxes and went on with native implemenation.

External link in WinJS, iframe or not, doesnt matter

I work on a Windows 8 app, and from a page that I use link hystory for running back and forward through the app, I also have 3 or 4 links to external websites(eg: facebook or my site). I tried to run them in iframe, or also to make them open in the default browser like simple links. Both method resulted in an error in base.js that says it can't handle my error (!?) I searched a lot before asking here. I watched msdn sample that works just fine, but if i copy what I need in my app results in the same error. I I use it from another page where I dont have forward history, it works, but i really need it on the front page. Any ideeas? Thank you very much.
LE:
This is my items.js code: ( for the items.html page )
(function () {
"use strict";
var appViewState = Windows.UI.ViewManagement.ApplicationViewState;
var ui = WinJS.UI;
ui.Pages.define("/pages/items/items.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
var listView = element.querySelector(".itemslist").winControl;
listView.itemDataSource = Data.groups.dataSource;
listView.itemTemplate = element.querySelector(".itemtemplate");
listView.oniteminvoked = this._itemInvoked.bind(this);
this._initializeLayout(listView, Windows.UI.ViewManagement.ApplicationView.value);
listView.element.focus();
WinJS.Utilities.query("a").listen("click", this.linkClickEventHandler, false);
},
// This function updates the page layout in response to viewState changes.
updateLayout: function (element, viewState, lastViewState) {
/// <param name="element" domElement="true" />
var listView = element.querySelector(".itemslist").winControl;
if (lastViewState !== viewState) {
if (lastViewState === appViewState.snapped || viewState === appViewState.snapped) {
var handler = function (e) {
listView.removeEventListener("contentanimating", handler, false);
e.preventDefault();
}
listView.addEventListener("contentanimating", handler, false);
var firstVisible = listView.indexOfFirstVisible;
this._initializeLayout(listView, viewState);
if (firstVisible >= 0 && listView.itemDataSource.list.length > 0) {
listView.indexOfFirstVisible = firstVisible;
}
}
}
},
linkClickEventHandler: function (eventInfo) {
eventInfo.preventDefault();
var link = eventInfo.target;
WinJS.Navigation.navigate(link.href);
},
// This function updates the ListView with new layouts
_initializeLayout: function (listView, viewState) {
/// <param name="listView" value="WinJS.UI.ListView.prototype" />
if (viewState === appViewState.snapped) {
listView.layout = new ui.ListLayout();
} else {
listView.layout = new ui.GridLayout();
}
},
_itemInvoked: function (args) {
var groupKey = Data.groups.getAt(args.detail.itemIndex).key;
WinJS.Navigation.navigate("/pages/split/split.html", { groupKey: groupKey });
}
});
})();
And from items.html I have different types of links: some of them links to other application pages, from where I can return with history buttons back/forward and some of them are links to external page. Simple link.These links crashes my app with the error that I mentioned below. If I erase the next line:
WinJS.Utilities.query("a").listen("click", this.linkClickEventHandler, false);
from my js script, external links works, but I dont have anymore history buttons in my others's app pages.
You are trying to use the navigation framework to navigate to an external URI. It's usually meant to be used within the application's local context and pages that can contain 'fragments' to load up into your main nav control.
I wouldn't hook anchor tags with your function call, instead in your linkClickEventHandler I would do the following to only hook your internal links
WinJS.Utilities.query(".nav").listen("click", linkClickEventHandler, false);
in turn your internal links would be
click me
This approach only hooks the navigation framework into your internal links. Another approach is to inspect the 'this.href' in your handler and if it contains http:// or https:// then call window.open instead

AngularJs + JQueryUI waiting for response

I am trying to make some useful directives with jQueryUI widgets for my AngularJS base application.
One of them works on "select" element and am ok with directives but only thing do not understand is this one:
When select list is populated from ajax request, how to tell to apply jqueryui widget when data is populated? Suppose it is with $watch but not sure how.
Edit:
In example I am trying to implement directive for the multiselect plugin.
Please note that I am simulating server reponse but putting everything in timeout.
Here is a code on plunker
You need to be $watching changes to the items list, then calling refresh on the multiselect plugin... Here is a plunk that shows the solution
angular.module('myui', [])
.directive('qnMultiselect', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elem, attr) {
//set up the plugin.
elem.multiselect({ allowClear: false });
//get the source of the ngOptions
var parts = attr.ngOptions.split(' ');
var source = parts[parts.length - 1];
//watch the options source and refresh the plugin.
scope.$watch(source, function(value) {
elem.multiselect('refresh');
});
}
};
});

jquerymobile and AJAX

seems to me that I didn't fully understand the concept behind jquerymobile, because I have no idea how to solve this issue.
What I want to do is load some HTML Content via AJAX, according to location.hash, put it into a new page and load this page.
But if I create a page myself by using the pagebeforechange event, jquerymobile just ignores it, creates its own div and my content won't be displayed.
How do I have to do it?
Edit:
This is how I am currently doing it, but it wont't work.
$(function() {
getPageContent(top.location.href, false);
$(document).bind( "pagebeforechange", function( e, data ) {
getPageContent(data.toPage, true);
});
});
function getPageContent(pageUrl, changedPage) {
var re = /.*\/#(.*)/;
var result;
result = re.exec(pageUrl);
window.page = result[1].substr(0,3);
window.id = result[1].substr(3);
window.ajaxUrl = "request.php?page="+window.page+"&id="+window.id;
$.ajax({
url: window.ajaxUrl,
success: function(data) {
if(data.error) {
alert(data.error);
}
else if(data.data) {
if(changedPage) {
changePage(data.data));
}
else {
$('#content[role="main"]').html(atob(data.data));
setupPage();
}
}
else {
alert("UNKNOWN ERROR: "+data);
}
}
});
}
function changePage(html) {
var div = "<div></div>";
var newPage = $(div).attr("data-role", "page").attr("data-url", window.page+window.id);
var header = $(div).attr("data-role", "header");
var content = $(div).attr("data-role", "content");
var footer = $(div).attr("data-role", "footer");
$("body").append(newPage);
newPage.append(header, content, footer);
content.html(html);
newPage.page();
}
Complete edit of the whole answer:
First. Set your body id to id=body. Then when you want to load the new page and change to it, use an ajax call like this:
$.get(window.ajaxUrl, function(data){
$('#body').append("<div id='newPage' data-role='page'></div>"); //Creates a new page.
$('#newPage').html(data); //Loads the html content into the new page.
$.mobile.changePage('#newPage'); //Navigates to the new page.
}
This sends an ajax call with the method GET to the url found in your window.ajaxUrl. If the call is successful, it creates a new page named "newPage", and fills it with the data received from the ajax call. Then redirects to the newly created page.
This jsFiddle shows the basics of how it works. However, it doesn't use any ajax call.
You have to refresh the page with jQueryMobile :
$("#your-page").trigger("create");
--Edit
<script>
$("#thepage").live("pageshow", function(){
$("#thepage).trigger("create");
});
</script>
Change the content of #thepage before 'pageshow' event
It does this for you automatically - just make a regular link to the page and jquery mobile will shwo the loading spinner, load it in the background via ajax, then transition to the new page.
Make sure all your pages are decide with unique IDs and data-role='page'. Check out the start guide here:
http://jquerymobile.com/demos/1.1.0/docs/about/getting-started.html

openWYSIWYG-Editor disappears on postback

It is working properly every time the page loads at the first time. However when we do a Postback the editor disappears with just the textarea.
The postback is happening due to a dropdown on the page.
<asp:TextBox runat="server" ID="TBClosingInstructions" TextMode="MultiLine" Rows="8" Columns="40" TabIndex="2" Font-Name="Verdana"></asp:TextBox><script language="JavaScript">generate_wysiwyg('TBClosingInstructions');</script>
I would like the editor to remain even after postback. I have tried the following code
if (Page.IsPostBack)
{
this.ClientScript.RegisterStartupScript(this.GetType(), "script", "<script language=\"JavaScript\">generate_wysiwyg('TBClosingInstructions');</script>", true);
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ClientScript", "<script language=\"JavaScript\">generate_wysiwyg('TBClosingInstructions');</script>", true);
}
Tried both registerStartupScript and registerClientScriptBlock individually to bind the javascript functions in every postback. But this doesn't work.
Is there any alternative? Please suggest.
There are a couple of methods that attach the editor to a textarea.
WYSIWYG.attach('all', mysettings);
This is what I was using which worked well if you content/form was not loaded dynamically.
Looking at the source code it attaches to the load event. This is probably why it isn't being attached.
WYSIWYG_Core.addEvent(window, "load", function generateEditor() { WYSIWYG._generate(id, settings); });
WYSIWYG.attachAll(mySettings);
I found this one works (all textareas), again looking at the source code it looks for every textarea in the DOM and does not attach to an event.
var areas = document.getElementsByTagName("textarea");
for (var i = 0; i < areas.length; i++) {
var id = areas[i].getAttribute("id");
if (id == null || id == "") continue;
this.setSettings(id, settings);
WYSIWYG_Core.includeCSS(this.config[id].CSSFile);
WYSIWYG._generate(id, settings);
}

Resources