WinJS How to select a listview item on page load - windows-8

I'm trying to select the first item in my listview control as soon as my nav page loads. The following code does not seem to have an effect. If i put the "selection.set(0)" code inside of a button click handler it will work fine, but it will not work as soon as the page loads which is my desired effect. Anyone have any ideas? I must be missing something very basic here!
HTML
<div id="basicListView"
data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource : ex.itemList.dataSource,
itemTemplate: select('#mediumListIconTextTemplate'),
layout : {type: WinJS.UI.ListLayout},
selectionMode: 'single',
tapBehavior: 'directSelect'
}">
</div>
JS
(function () {
"use strict";
var _lv = null;
WinJS.UI.Pages.define("/pages/page2/page2.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) {
// TODO: Initialize the page here.
_lv = document.getElementById("basicListView").winControl;
// This should select the first item in the listview though it seems to have no effect.
_lv.selection.set(0);
},
});
})();

I think your problem is that the list is not populated when you try to access it.
Try to put this code in your ready event so you will know when the list is ready:
ready: function (element, options) {
var listView = element.querySelector(".itemslist").winControl;
listView .onloadingstatechanged = function (args) {
if (args.srcElement === listView .element && listView .loadingState === "complete") {
//and here you set your item
_lv = document.getElementById("basicListView").winControl;
_lv.selection.set(0);
}
};
}

Related

Dojo enable button by event handler

I am working with IBM Content Navigator 2.0.3, that uses DOJO 1.8 for the GUI development. I am new in dojo, and I have to enhance one of the forms: add an event handler to the dataGrid so when the row of the grid is selected one of the buttons become enabled.
I've managed to add event handler as was advised in this issue: dojo datagrid event attach issue
but I still can't enable the button. Here is html of the form:
Add
Remove
<div class="selectedGridContainer" data-dojo-attach-point="_selectedDataGridContainer">
<div class="selectedGrid" data-dojo-attach-point="_selectedDataGrid" ></div>
</div>
The attached image describes how it looksenter image description here.enter image description here
And the js file code of postCreate function is following:
postCreate: function() {
this.inherited(arguments);
this.textDir = has("text-direction");
domClass.add(this._selectedDataGridContainer, "hasSorting");
this._renderSelectedGrid();
this.own(aspect.after(this.addUsersButton, "onClick", lang.hitch(this, function() {
var selectUserGroupDialog = new SelectUserGroupDialog({queryMode:"users", hasSorting:true, callback:lang.hitch(this, function (user) {
this._onComplete(user);
this._markDirty();
})});
selectUserGroupDialog.show(this.repository);
})));
this.own(aspect.after(this.removeUsersButton, "onClick", lang.hitch(this, function() {
if (this._selectedGrid != null) {
var selectedItems = this._selectedGrid.selection.getSelected();
if (selectedItems.length > 0) {
array.forEach(selectedItems, lang.hitch(this, function(item) {
this._selectedGrid.store.deleteItem(item);
}));
}
this._selectedGrid.selection.clear();
this._selectedGrid.update();
}
this._markDirty();
})));
// the following handler was added by me
dojo.connect(this.myGrid, 'onclick', dojo.hitch(this, function(){
console.log(" before ");
this.removeUsersButton.set('disabled', true);
console.log(" after ");
}));
},
so this.own(aspect.after(this.removeUsersButton..... works fine and worked before my interference. So it somehow accesses this.removeUsersButton and processes the event. But my handler dojo.connect(this.myGrid.... only prints console.log() before and after without enabling the Remove button. The Button has no Id, only data-dojo-attach-point. How do I enable the Remove button when the daaGrid is selected?
With this.removeUsersButton.set('disabled', true); you are setting the button to be disabled. If you want to enable it you need to set it to false.
this.removeUsersButton.set('disabled', false);

Dojo ListItem with Child Inputs

I have a dojo list item that is clickable.. But at the same time we like to put input elements inside the list item. The problem is that if you click on the child element(example checkbox) the listitem onclick intercepts the call first(which seems opposite of the html bubble up format). So we cannot call stoppropagation on the child element to stop the listitem from changing the page.
In the example below you will see the listitem alert come up before the checkbox alert..
How do you handle having input elements in a listitem without triggering the listitem..
fiddle::http://jsfiddle.net/theinnkeeper/HFA36/1/
ex.
var list1 = registry.byId("myList");
var item = new ListItem ({
label: "A \"programmatic\" ListItem",
moveTo: "#",
noArrow:true,
onClick : function() {
alert("listItem clicked !" + event.target.type);
}
});
list1.addChild(item);
var check = new cb({onClick:function(){alert("checkbox clicked");event.stopPropagation();}});
check.placeAt(item.containerNode.firstChild);
check.startup();
I had a similar problem a while back and noticed that the dojox/mobile/ListItem is not really great when adding extra event handlers to it (checkboxes, touch gestures, ...), so to solve that I usually extend dojox/mobile/ListItem and fix the events by myself.
For example:
var CheckedListItem = declare("dojox/mobile/CheckedListItem", [ ListItem ], {
_initializeCheckbox: function() {
this.checkbox = new CheckBox({
});
domConstruct.place(this.checkbox.domNode, this.containerNode.firstChild, "last");
this.checkbox.startup();
this.checkbox.onClick = this.onCheckboxClick;
},
onCheckboxClick: function() { },
_setOnCheckboxClickAttr: function(handler) {
this.onCheckboxClick = handler;
if (this.checkbox !== null && this.checkbox !== undefined) {
this.checkbox.onClick = handler;
}
},
_onClick: function(e) {
if (e.target !== this.checkbox.domNode) {
this.inherited(arguments);
}
},
postCreate: function() {
this.inherited(arguments);
this._initializeCheckbox();
}
});
Due to overriding _onClick() and adding additional checks I managed to get the intended behavior.
A full example can be found here: http://jsfiddle.net/LQ6Mb/

TableView 'click' listener being ignored

I am dynamically building a TableView in my controller, which works fine: The initial table displays the initial collections data as expected.
The problem is that the TableView's 'click' event listener is ignored when I click on the table rows. I am testing in the browser, and I never even see the console event file (see comments in controller file). All relevant code snippets below:
In my alloy.js I setup a backbone collection:
function defaultTodo(name) { return {name: name, done: false}; }
function doneTodo(name) { return {name: name, done: true}; }
Alloy.Collections.todos = new Backbone.Collection();
Alloy.Collections.todos.reset([
defaultTodo('Apples'), // create not yet done todo
defaultTodo('Banana'),
defaultTodo('Paper Towels'),
defaultTodo('Broccoli'),
doneTodo('Beans'), // create already done todo
doneTodo('Water'),
doneTodo('Blueberries'),
doneTodo('Stir Fry')
])
Here is my index.js controller:
var todos = Alloy.Collections.todos;
function redrawTable() {
// clear all the old data
// See http://developer.appcelerator.com/question/49241/delete-all-rows-in-a-tableview-with-a-single-click
$.table.setData([]);
// Create and add the TableViewSections
var alreadyDone = Ti.UI.createTableViewSection({ headerTitle: "Already Done" });
var needsDoing = Ti.UI.createTableViewSection({ headerTitle: "Needs Doing" });
$.table.appendSection(needsDoing);
$.table.appendSection(alreadyDone);
// Add the todo to the appropriate sections
todos.forEach(function(todo) {
var section = todo.get('done') ? alreadyDone : needsDoing;
addEntry(todo, section);
});
// Add the click listener
// THIS LISTENER IS IGNORED ********************************
$.table.addEventListener('click', function(e) {
console.log(e);
todos.at(e.index).set('done', true);
todos.trigger('change');
});
// Helper function to add a row to a section
function addEntry(todo, section) {
var row = Ti.UI.createTableViewRow({
title: todo.get('name'),
className: "row"
});
section.add(row);
}
}
// Redraw our table each time our todos collection changes
todos.on('change', redrawTable);
// Trigger a change event to draw the initial table
todos.trigger('change');
$.index.open();
And here is index.xml view file:
<Alloy>
<Window class="container">
<Label id="test" class="header">My Grocery List</Label>
<TextField id="newItem"/>
<TableView id="table">
</TableView>
</Window>
</Alloy>
UPDATE: Working Code
In addition to the changes below, I also added onClick="markDone" to the xml.
function markDone(e) {
console.log(e.row.todo);
e.row.todo.set('done', true);
todos.trigger('change');
}
function redrawTable() {
// clear all the old data
// See http://developer.appcelerator.com/question/49241/delete-all-rows-in-a-tableview-with-a-single-click
$.table.setData([]);
var rows = [];
var done = [];
var doing = [];
// Add the todo to the appropriate sections
todos.forEach(function(todo) {
var row = Ti.UI.createTableViewRow({
title: todo.get('name'),
className: "row"
});
row.todo = todo;
todo.get('done') ? done.push(row) : doing.push(row);
});
// Create and add the TableViewSections
rows.push(Ti.UI.createTableViewSection({ headerTitle: "Needs Doing" }));
rows = rows.concat(doing);
rows.push(Ti.UI.createTableViewSection({ headerTitle: "Already Done" }));
rows = rows.concat(done);
$.table.setData(rows);
};
I created brand new project using files which you provided and eventListener is working perfectly fine. However there are couple other bugs:
Creating listener inside redrawTable() function, which is executed every time you click on something in TableView. As a result at the beginning you have one eventListener but after every click all listeners are duplicated.
Using index property in event handler to find index of Backbone model object to update. index property is indicating at which place given row was displayed in your TableView. When you are moving rows between sections their index are changing. In your case it's better to check e.row.name property and use Backbone.Collection.findWhere() method. If user can have two items with the same name on the list, then you have to create additional property to determine which object in model should be changed.
You should add rows to section before section are added to table. In your case table is very simple so instead of doing loops you can just create one simple array of objects (with title and optional header properties) and pass it to $.table.setData().
It's good to wait for postlayout event triggered on main view before triggering any custom events to make sure that the whole view was created and all objects are initiated.
Check rewrote index.js code below to see how it could be done.
var todos = Alloy.Collections.todos;
function redrawTable() {
var done = todos.where({done: true}).map(function(elem) {
return { title: elem.get('name') };
});
if (done.length > 0) {
done[0].header = 'Already Done';
}
var notdone = todos.where({done: false}).map(function(elem) {
return { title: elem.get('name') };
});
if (notdone.length > 0) {
notdone[0].header = 'Needs Doing';
}
$.table.setData( done.concat(notdone) );
}
$.table.addEventListener('click', function(e) {
todos.where({ name: e.row.title }).forEach(function(elem){
elem.set('done', !elem.get('done'));
});
todos.trigger('change'); // Redraw table
});
// Redraw our table each time our todos collection changes
todos.on('change', redrawTable);
// Trigger a change event to draw the initial table
$.index.addEventListener('postlayout', function init(){
todos.trigger('change');
// Remove eventListener, we don't need it any more.
$.index.removeEventListener('postlayout', init);
})
$.index.open();
redrawTable() could have a little more refactor but I left it so it's easier to read.
To read more about manipulating TableView check this Appcelerator documentation page.

Header and Footer keep showing up with modal pop up window

I just want to show basic HTML without the header and footer of my main page when using a modal window.
How can one do that in MVC3/4?
Here is an example of what is happening...
Not sure why it is doing that.
This is a basic jquery modal window call
$(function () {
//$('a.tempDlg').live("click", function (event) { loadDialog(this, event, '#edit-set'); });
//$('a.AddPatDlg').live("click", function(event) {loadDialog(this, event, '#addPat');});
//debugger;
$('a.addEncounter').live("click", function (event) { loadDialog(this, event, '#DisplayUniqueEncounters'); });
$('a.SearchEncounter').live("click", function (event) { loadDialog(this, event, '#searchEncounter'); });
//$("#sID").click(function (event) { loadDialogByClick(this, event, '#searchEncounter'); });
});
function loadDialog(tag, event, target) {
//debugger;
event.preventDefault();
var $loading = $('<img src="<%=Url.Content("~/Images/ajax-loader.gif")%>" alt="loading" class="ui-loading-icon">');
var $url = $(tag).attr('href');
var $title = $(tag).attr('title');
var $dialog = $('<div></div>');
$dialog.empty();
$dialog
.append($loading)
.load($url)
.dialog({
autoOpen: false
, title: $title
, width: 1200
, modal: true
, minHeight: 550
, show: 'fade'
, hide: 'fade'
});
$dialog.dialog('open');
};
I have done this before without including the header and footer, and I forget how it was done? I must be missing a step.
You can also set the Layout = null at the top of the page
That is correct... I want to give nemesv credit for this answer, but he didn't answer the question. So I will just say that he was right. You need to return a partialView(), not just a regular view... Returning a regular view always gets all of the other MVC markup. Thanks...

Dojo Tooltip only shows after first mousover event

I'm using dojo's event delegation to connect a Tooltip widget to dynamically generated dom nodes.
The Dojo site explains event delegation this way:
"The idea behind event delegation is that instead of attaching a
listener to an event on each individual node of interest, you attach a
single listener to a node at a higher level, which will check the
target of events it catches to see whether they bubbled from an actual
node of interest; if so, the handler's logic will be performed."
Following is my code implementation. It works beautifully ... EXCEPT, the tooltip only shows AFTER the first mouse over event. When I first mouseover the node, the event fires perfectly, but the tooltip doesn't render. It will only show the consequent mouseover events. On the first mouseover event, I can watch the Firebug console and see the xhr.get go to the database and get the correct data. If I comment out the tooltip and throw in a simple alert(), it works the first time.
Any suggestions on how to get the Tooltip to show on the first mouseover event? Thanks in advance!
<div class="col_section" id="my_groups">
<div class="col_section_label">My Groups</div>
<ul>
<?php
foreach($myGroups as $grp) {
echo '<li><a class="myGroupLink" id="grp'.$grp['grp_id'].'">'.$grp['name'].'</a></li>';
}
?>
</ul>
</div>
<script>
require(["dojo/on",
"dojo/dom",
"dijit/Tooltip",
"dojo/_base/xhr",
"ready!"], function(on, dom, Tooltip, xhr) {
// Get Group ToolTip
var myObject = {
id: "myObject",
onMouseover: function(evt){
var grp_id = this.id;
var content = '';
xhr.get({
url: "getGrpInfo.php",
handleAs: "json",
content: {
grp_id: grp_id,
content: "tooltip"
},
load: function(info) {
if(info == 0) {
content = '<div class="grpToolTip">';
content += ' Information about this group is confidential';
content += '</div>';
} else {
content = '<div class="grpToolTip">';
content += ' <img src="../ajax/getimg.php?id='+info.logo_id+'" />';
content += ' <div style="text-align:center">'+info.name+'</div>';
content += '</div>';
}
new Tooltip({
connectId: [grp_id],
label: content
});
},
error: function() {}
});
}
};
var div = dom.byId("my_groups");
on(div,".myGroupLink:mouseover",myObject.onMouseover);
});
</script>
Your Tooltip does not show on the first onmouseover because it does not exist at the moment the onmouseover event was fired.
dijit/Tooltip instances manage theirs mouse events themselves, so you do not have to manage onmouseover/onmouseout and you probably did so because you do not want to preload data or you want to load data every time the tooltip is about to show.
Beside dijit/Tooltip instances you can use Tooltip.show(innerHTML, aroundNode, position) and Tooltip.hide(aroundNode) to display tooltips, but in that case you will have to manage mouse events yourself, which is what you need, because from the UX perspective, you do not want to show single tooltip, you want to:
Show a tooltip indicating information is being loaded.
Then either:
display XHR loaded information if a user still hover over the node
cancel XHR and hide tooltip on mouseout
Here is working example: http://jsfiddle.net/phusick/3hmds/
require([
"dojo/dom",
"dojo/on",
"dojo/_base/xhr",
"dijit/Tooltip",
"dojo/domReady!"
], function(
dom,
on,
xhr,
Tooltip
) {
on(dom.byId("groups"), ".group-link:mouseover", function(e) {
var target = e.target;
Tooltip.show("Loading...", target);
var def = xhr.post({
url: "/echo/html/",
content: { html: target.textContent},
failOk: true,
load: function(data) {
Tooltip._masterTT.xhr = null;
Tooltip._masterTT.containerNode.innerHTML = data;
Tooltip._masterTT.domNode.width = "auto";
},
error: function(e) {
if (e.dojoType != "cancel") {
console.error(e);
}
}
});
Tooltip._masterTT.xhr = def;
});
on(dom.byId("groups"), ".group-link:mouseout", function(e) {
var target = e.target;
Tooltip.hide(target);
if (Tooltip._masterTT.xhr) {
Tooltip._masterTT.xhr.cancel();
}
});
});​
As usual, I was over-thinking the problem, focusing on event registration rather than on simply creating the tooltips when the page loads. So, it's really stupidly simple:
query for the nodes
iterate through them and create the tooltips pointing to each node.
var myGroupsList = query("a.myGroupLink"); // query nodes based on class
array.forEach(myGroupsList,function(entry,i){ // iterate through
var grp_id = entry.id;
var content = '';
xhr.get({ // get data via xhr.get
url: "getGrpInfo.php",
handleAs: "json",
content: {
grp_id: grp_id,
content: "tooltip"
},
load: function(info) {
if(info == 0) {
content = '<div class="grpToolTip">';
content += ' Information about this group is confidential';
content += '</div>';
} else {
content = '<div class="grpToolTip">';
content += ' <img src="../ajax/getimg.php?id='+info.logo_id+'" />';
content += ' <div style="text-align:center">'+info.name+'</div>';
content += '</div>';
}
new Tooltip({ // create tooltip
connectId: [entry.id],
label: content
});
},
error: function() {}
});
});