I'm working on Titanium and developing for iOS devices. In my application I have a tableview that is filled with sections with rows created by a function that uses the data received from a HTTPClientobject response. Each row has a view and inside the view there's a button and label.
The button has a click event which works fine. I added a click event to the view that stores the button, but when I click on the view, the event isn't fired, but if I click on the button, both the button's event and the view's event are fired. This is not how it is supposed to behave, since I want the view's event to do something completely different from the button's event.
Why isn't the view's click event being fired when I click on the view? Why does the event fires when I click on the button?
Here's how I create the rows:
function addToDo(title, priority){
var that = {};
var row = Ti.UI.createTableViewRow({height:80});
that.currentPriority = priority;
that.resolveColor = function(tmpPriority){
switch(tmpPriority){
case 0: backgroundColorPriority = "#da362a"; break;
case 1: backgroundColorPriority = "#da6c2a"; break;
case 2: backgroundColorPriority = "#da962a"; break;
case 3: backgroundColorPriority = "#dacb2a"; break;
}
return backgroundColorPriority;
}
var rowLayout = Ti.UI.createView({
backgroundColor : 'transparent'
});
var checkbox = Ti.UI.createButton({
top: 25,
left: 5,
width: 30,
height: 30,
borderColor: 'white',
borderWidth: 2,
borderRadius: 1,
backgroundColor: '#b1b1b1',
backgroundImage: 'NONE',
zIndex:10,
value: false //value is a custom property in this case here.
});
rowLayout.add(checkbox);
//Attach some simple on/off actions
checkbox.on = function(item) {
this.backgroundColor = '#62b425';
item.currentRow.backgroundColor = "#101010";
this.value = true;
};
checkbox.off = function(item) {
this.backgroundColor = '#b1b1b1';
item.currentRow.backgroundColor = item.resolveColor(item.currentPriority);
this.value = false;
};
checkbox.addEventListener('click', function(e) {
if(false == e.source.value) {
e.source.on(that);
} else {
e.source.off(that);
}
});
// Create a Label.
var todoTitleLabel = Ti.UI.createLabel({
text : title,
color : 'white',
font : {fontSize:11},
left : 40,
textAlign : 'center'
});
// Add to the parent view.
rowLayout.add(todoTitleLabel);
row.add(rowLayout);
rowLayout.addEventListener('click', function(e){
// Whatever I put here isn't executed when I click on the rowLayout, instead I have to click the button to fire this event, that shouldn't happen
});
var backgroundColorPriority = that.resolveColor(that.currentPriority);
row.backgroundColor = backgroundColorPriority
that.currentRow = row;
return that.currentRow;
}
This function is called in a HTTPClient onload:
var clientTask = Ti.Network.createHTTPClient({
onload : function(e){
var responseTask = JSON.parse(this.responseText);
var entriesTask = responseTask.tasks;
var todoSectionView = Ti.UI.createTableViewSection({
headerTitle : responseTask.name
});
data.push(todoSectionView);
for( var j=0; j < entriesTask.length; j++){
var tmpRow = addToDo(entriesTask[j].name, entriesTask[j].priority);
todoSectionView.add(tmpRow);
}
// add the data to the tableview
table.data=data;
self.updateLayout();
},
timeout : 60000
});
I'd probably test this by creating an event handler for the todoTitleLabel or giving it a background color that is different from the row to see if I'm able to click on the row itself. Maybe the objects on it are blocking it? Perhaps you can accomplish what you are trying to do by adding the click event to the label instead?
Don't add the eventlistener to the row, section or rowlayout. It will cause problems on iOS.
Instead, add the eventlistener to your table view, e.g.:
tableView.addEventListener('click', function(e){
var rowNumber = e.index;
alert(rowNumber);
});
The example will alert the number of the selected row.
Related
With the coming of multi-process Firefox, I have decided to revamp my addon. It is a toolbar addon that was built on XUL. Now I want to build it using the Addon SDK.
The old XUL overlay allowed for onMouseOver events for buttons. But the new addon SDK only has the one listener for click.
How can I get an onMouseOver (Hover) event for a toolbar button?
Maybe there is some way to add css (:hover) to the button element?
I found this, and am working on getting it in order, but maybe there's a better way?
Here is what I have so far:
var {Cu, Cc, Ci} = require("chrome");
Cu.import('resource://gre/modules/Services.jsm');
var aDOMWindow = Services.wm.getMostRecentWindow('navigator:browser');
aDOMWindow.addEventListener('mouseover', onSpatMouseover, true);
function onMyMouseover(event){
if (event.target.nodeName == 'toolbarbutton'){
console.log(event.explicitOriginalTarget.nodeName);
if(event.currentTarget.nodeName == '#MyButton'){
console.log("found the button");
}
}
}
But it does not yet find #MyButton.
First of all, error message you're getting already tells you how to make it work.
But it's not necessarily what you need anyway, usually sdk/view/core provides access to the underlying XUL elements through one of its 3 methods.
Here is a complete example of how to do this. There are two functions, actually, one for mouseover and one for mouseout. If you change the icon of a button using mouseover, you need mouseout to change it back to normal.
const { browserWindows } = require("sdk/windows");
const { CustomizableUI } = require('resource:///modules/CustomizableUI.jsm');
const { viewFor } = require("sdk/view/core");
const { ActionButton } = require("sdk/ui/button/action");
var myButton = ActionButton({
id: "mybutton",
label: "My Button",
icon: { "16": "./icon-16.png", "32":"./icon-32.png", "64": "./icon-64.png" },
onClick: function(state) {
console.log("My Button was clicked");
}
});
//create a mouseover effect for a control
exports.MouseOver = (whatbutton, whatwindow, whatfunction) =>{
CustomizableUI.getWidget( viewFor(whatbutton).id ).forWindow(whatwindow).node.addEventListener('mouseover', whatfunction, true);
};
exports.MouseOut = (whatbutton, whatwindow, whatfunction) =>{
CustomizableUI.getWidget( viewFor(whatbutton).id ).forWindow(whatwindow).node.addEventListener('mouseout', whatfunction, true);
};
function myMouseOverFunction(){
console.log("mousing over...");
}
function myMouseOutFunction(){
console.log("mousing out...");
}
//add events to the browser window
for(let w of browserWindows){
exports.MouseOver(mybutton, viewFor(w), myMouseOverFunction);
exports.MouseOut(mybutton, viewFor(w), onMouseOutFunction );
}
I have a CustomizableUI.jsm button i add to the toolbar. On click of this it opens a panel which has a chrome page loaded.
I want all windows to open this same panel. So my thought was to add the panel to Services.appShell.hiddenDOMWindow and then open it anchored to the the CustomizableUI.jsm button.
However I'm having trouble adding the panel to the hidddenDOMWindow.
This code works fine from scratchpad if you make the first line be var win = window. But if you make it be var win = Services.appShell.hiddenDOMWindow it has trouble appending the panel to the popupset. So weird.
Code here is the appShell hidden window code. If you make it var win= window it works fine:
var win = window; //Services.appShell.hiddenDOMWindow;
var panel = win.document.createElementNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul','panel');
var props = {
type: 'arrow',
style: 'width:300px;height:100px;'
}
for (var p in props) {
panel.setAttribute(p, props[p]);
}
var popupset = win.document.createElementNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul','popupset');
popupset.appendChild(panel);
win.document.documentElement.appendChild(popupset);
panel.addEventListener('popuphiding', function (e) {
e.preventDefault();
e.stopPropagation();
//panel.removeEventListener('popuphiding', arguments.callee, false); //if dont have this then cant do hidepopup after animation as hiding will be prevented
panel.addEventListener('transitionend', function () {
panel.hidePopup(); //just hide it, if want this then comment out line 19 also uncomment line 16
//panel.parentNode.removeChild(panel); //remove it from dom //if want this then comment out line 18
}, false);
panel.ownerDocument.getAnonymousNodes(panel)[0].setAttribute('style', 'transform:translate(0,-50px);opacity:0.9;transition: transform 0.2s ease-in, opacity 0.15s ease-in');
}, false);
panel.openPopup(window.document.documentElement, 'overlap', 100, 100);
http://docs.appcelerator.com/titanium/3.0/?mobile=/api/Titanium.UI.ActivityIndicator
Is it possible to and how would I add an ActivityIndicator to a listView listItem? Possibly via the listView template on selected items...
Thanks in advance!
Yes, it is possible, here's a snippet:
First start by defining list item templates:
// Some text row
var someTextTemplate = {
properties: {
accessoryType: Ti.UI.LIST_ACCESSORY_TYPE_NONE
},
childTemplates: [ // Add view subcomponents to the ListItem
{
// Display a Label
type: 'Ti.UI.Label',
bindId: 'someRowText',
properties: {
font: {fontSize: '14dp'}
}
}
]
};
//This is your loading template
var loadingTemplate = {
properties: {
accessoryType: Ti.UI.LIST_ACCESSORY_TYPE_NONE
},
childTemplates: [ //And here is where the activity indicator goes
{
// Display an activity indicator
type: 'Ti.UI.ActivityIndicator',
// If there is a 'loadingIndicator' dictionary in the ListDataItem,
// that data binds with this view subcomponent (useful for changing
// the loading message, for example)
bindId: 'loadingIndicator',
properties: {
// Set the indicator properties
font: { fontSize: '22dp'},
width: Titanium.UI.SIZE,
height: Titanium.UI.SIZE,
// If you don't set visible to true, the indicator will not show,
// because unlike other UI elements, it is hidden by default
visible: true,
//Other styles available, just check the component doc
style: Titanium.UI.iPhone.ActivityIndicatorStyle.PLAIN
}
}
]
};
Then setup your ListView
// Create the list section
var listSection = Titanium.UI.createListSection();
// Add the list section to a list view
var listView = Titanium.UI.createListView({
width: Ti.UI.FILL,
height: Ti.UI.SIZE,
layout: 'vertical',
touchEnabled: true,
sections: [listSection],
templates: {'rowText': someTextTemplate, 'loading': loadingTemplate },
defaultItemTemplate: 'rowText',
showVerticalScrollIndicator: true
});
Finally, add some list data items
var someData = [];
// This will add a row with a label, because we've set 'rowText' as our
// default ListView template
someData.push({
someRowText: { text: 'Some text row 1'}
});
// This will also show another label row, because we're specifying
// the template to use, in this case the label one
someData.push({
someRowText: { text: 'Some text row 2'},
template: 'rowText'
});
// Now we're going to use the 'loading' template, therefore showing
// the activity indicator in the row
someData.push({
loadingIndicator: { message: 'Please wait while transfering data from the mothership...' },
template: 'loading'
});
//Add our data items to the listview section
listSection.setItems(someData);
You can also mix multiple templates, but I've tried to simplify the example as much as possible.
I have updated to v3.0 and found this issue in IE9 & Chrome.
I have a button that creates a new chart based on the data found.
The graph scale yAxis changes? (Note: the chart is logarithmic chart).
And sometimes the graph changes into:
Sorry for not having a real example: but i noticed this when pressing the custom button (after 5/6 times) - this issue appears:
Notes:
1) The button is created with the chart.
2) The chart might updated every 5sec - if data was changed
// handle detailed chart refresh button
function showResetZoomButton(pb_detailed_chart)
{
// load refresh images
var ResetZoomJPG = 'images/gallery/reset_zoom.jpg';
var ResetZoomPressedJPG = 'images/gallery/reset_zoom_pressed.jpg';
// add refresh (pressed) image
var imgResetZoomPressed = pb_detailed_chart.renderer.image(ResetZoomPressedJPG, pb_detailed_chart.chartWidth-112,10,24,20);
imgResetZoomPressed.add();
imgResetZoomPressed.css({'cursor':'pointer'});
imgResetZoomPressed.attr({'title':'Reset Zoom'});
// add refresh image
var imgResetZoom = pb_detailed_chart.renderer.image(ResetZoomJPG, pb_detailed_chart.chartWidth-112,10,24,20);
imgResetZoom.add();
imgResetZoom.css({'cursor':'pointer'});
imgResetZoom.attr({'title':'Reset Zoom'});
// init in-action/out-action for mouse event
var inAction = "mouseover";
var outAction = "mouseout";
if ( $.browser.mozila )
{
inAction = "mouseenter"; outAction = "mouseleave";
}
imgResetZoom.on(inAction, function(){
imgResetZoomPressed.show();
imgResetZoom.hide();
});
imgResetZoom.on(outAction, function(){
imgResetZoom.show();
imgResetZoomPressed.hide();
});
imgResetZoomPressed.on(inAction, function(){
imgResetZoomPressed.show();
imgResetZoom.hide();
});
imgResetZoomPressed.on(outAction, function(){
imgResetZoom.show();
imgResetZoomPressed.hide();
});
// refresh chart
imgResetZoomPressed.on('click',function(){
// check if master found, and if real time disabled
if (pb_master_chart && enable_lastRoundsChart_realtime == 0)
{
// master chart found
// remove plotBand
pb_master_chart.xAxis[0].removePlotBand('mask-before');
pb_master_chart.xAxis[0].removePlotBand('mask-after');
pb_master_chart.xAxis[0].addPlotBand({
id: 'mask-before',
from: -1,
to: 99999,
color: 'rgba(0, 0, 0, 0.2)'
})
}
// reset detailed graph
createDetail(cache_last_rounds.last_rounds_data, window.show_top_round_ids);
});
}
I am creating Array of LabelView in my application during the run time and adding it to a TableView. But click EventListener not working for LabelView, Here is my sample code
var picRow = Titanium.UI.createTableViewRow();
var photoContainer = Ti.UI.createView({
top:0,
width:300,
left:15,
right:5,
height:200
})
picRow.add(photoContainer);
var shareTable = Ti.UI.createTableView({
data:[picRow],
top:10,
left:0,
right:0,
height:250,
separatorColor: '#ccc',
backgroundColor:'transparent'
});
win.add(shareTable);
var pushleft = 5;
var pushtop = 5;
var images = [];
for (var i = 0; i < imageArray.length; i++){
images[i] = Ti.UI.createLabel({
backgroundImage: imageArray[i].image, // path to image at applicationDataDirectory
width: 70 ,
height: 70,
"tickOption":false,
"index":i,
"picId":imageArray[i].picId,
left: pushleft + 25, // logic for positioning
top: pushtop + 5
});
pushleft = pushleft + 80;
pushtop = pushtop + 50;
photoContainer.add(images[i]);
images[i].addEventListener('click', function(e) {
alert(e);
});
}
Here I am not getting any alert while clicking on the label view. Also I am not getting any error. Anyone help me to solve this issue. Thanks in Advance. I am using Titanium 1.7.5 and ios
it is a best practice to put the eventlistener on the whole row and then look at the click event object to determine which object received the click.
so for example you would look for the picId of the object, if it existed, you would know that a label was clicked