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.
Related
I am using the render event to alter the positioning of of my x-axis labels on a highchart. It works great - centering labels between ticks on a datetime x-axis and removing the last label.
When I export the chart - with the same setup - the function is called (see centerTimelineLabels below), but it cannot access the rendered x-axis labels. Please see the images below showing the different x-axis labels in the DOM and as an exported PNG.
jsfiddle here: https://jsfiddle.net/SirMunchington/36xcbr7m/52/
Specifically, this.container inside of the function, is an empty wrapper on export... no children.
Is there a way to access and manipulate the x-axis labels in a highchart when exporting?
exporting: {
chartOptions: { // specific options for the exported image
chart: {
backgroundColor: '#ffffff',
events: {
render: centerTimelineLabels
}
}
},
...
var centerTimelineLabels = function() {
var labels = $('.highcharts-xaxis-labels span', this.container).sort(function(a, b) {
return +parseInt($(a).css('left')) - +parseInt($(b).css('left'));
});
$(labels).css('margin-left',
(parseInt($(labels.get(1)).css('left')) - (parseInt($(labels.get(0)).css('left')) + parseInt($(labels.get(1)).width()))) / 2
);
$(labels.get(this.xAxis[0].tickPositions.length - 1)).remove();
};
CORRECT X-AXIS VIA WEB
INCORRECT X-AXIS VIA EXPORT
Thank you for the demo.
Try to use this config - notice that the render event triggers after each chart redraw:
"events": {
render() {
let chart = this,
xAxis = chart.xAxis[0],
ticks = xAxis.ticks,
firstTick = ticks[xAxis.tickPositions[0]],
secondTick = ticks[xAxis.tickPositions[1]],
ticksDistance = secondTick.mark.getBBox().x - firstTick.mark.getBBox().x;
for (let i in ticks) {
let tick = ticks[i];
if (!tick.isLast) {
tick.label.translate(ticksDistance / 2, 0)
}
}
}
}
Demo: https://jsfiddle.net/BlackLabel/o06r1yfw/
To hide the last label set the xAxis.showLastLabel property to false.
API: https://api.highcharts.com/highcharts/xAxis.showLastLabel
Im trying to get my jspdf to not save a blank page PDF. I been trying many examples, but nothing works :(. My table content is saved correct, with a image on the second page of the PDF, but my first page is blank.
var pdf = new jsPDF('o', 'pt', 'a6');
//pdf.autoTable(this.columns, this.data);
//var width = pdf.internal.pageSize.width;
//var height = pdf.internal.pageSize.height;
pdf.addPage('1800','900');
pdf.addImage(imgData, 'PNG', 120, 40, 120, 100);
pdf.setTextColor(0,0,0);
pdf.text(120, 20, 'BOOKINGS');
pdf.setFontSize(22);
// 'o', 'pt', 'a4'
// 'p', 'pt', 'letter'
// source can be HTML-formatted string, or a reference
// to an actual DOM element from which the text will be scraped.
source = jQuery('.dataTables_wrapper')[0];
// we support special element handlers. Register them with jQuery-style
// ID selector for either ID or node name. ("#iAmID", "div", "span" etc.)
// There is no support for any other type of selectors
// (class, of compound) at this time.
specialElementHandlers = {
// element with id of "bypass" - jQuery style selector
'#bypassme': function (element, renderer) {
// true = "handled elsewhere, bypass text extraction"
return true
}
};
margins = {
top: 120,
bottom: 0,
left: 0,
width: 2000
};
// all coords and widths are in jsPDF instance's declared units
// 'inches' in this case
pdf.fromHTML(
source, // HTML string or DOM elem ref.
margins.left, // x coord
margins.top, { // y coord
'width': margins.width, // max width of content on PDF
'elementHandlers': specialElementHandlers
},
function (dispose) {
// dispose: object with X, Y of the last line add to the PDF
// this allow the insertion of new lines after html
pdf.save('bookings.pdf');
}, margins);
}
The first page is blank because adding a page is the first call you make after calling the jsPDF constructor. The constructor does already create a (first) blank page. To get rid of the additional empty page at the start of the document, either delete the first page calling doc.deletePage(1), or do not add a page after the constructor is being called.
How do I hide the bar data by clicking the bar and refresh the chart? I would like to have almost the same functionality as clicking on the legend.
Jsfiddle: https://jsfiddle.net/Nadiyaka/005z7dut/1/
For example, if I click on 'Asia' bar, I want the data to become hidden and the chart to be reloaded to see other data bigger.
So far I'm able only to hide the data, but the chart isn't refreshing:
series: [{
data: [1052, 954, 4250, 740, 38],
events: {
click: function(e) {
var chart = $("#container").highcharts();
index = event.point.x;
chart.series[0].data[index].graphic.hide();
chart.series[0].data[index].dataLabel.hide();
}
}
}]
There is no option for hiding points (except the points in pie series), but you can achieve the same effect by setting the point's value to null.
events: {
click: function(e) {
var point = e.point;
point.series.chart.pointer.reset(false); // this is needed to prevent the tooltip from moving around
point.update({
y: null,
holdY: point.y // I preserve original value needed on showing
});
}
}
For showing the columns, attach events to labels
load: function() {
var chart = this,
points = this.series[0].data;
points.forEach(function(point) {
chart.xAxis[0].ticks[point.x].label.on('click', function() {
if (point.y === null) {
point.update({
y: point.holdY
});
}
});
});
}
example: https://jsfiddle.net/005z7dut/2/
Is there any way to toggle the custom button text in highcharts?
toggleButton: {
text: 'ON',
onclick: function () {
console.log($(this).text());
$(this).text(function (i, text) {
return text === "ON" ? "OFF" : "ON";
});
}
}
Demo Link
this in callback refers to the chart itself. Buttons are stored in chart.exportSVGElements array. So, here is the solution: http://jsfiddle.net/knmb38dy/1/
toggleButton: {
text: 'ON',
onclick: function () {
var button = this.exportSVGElements[0], // 0 = text element, 1 = rect button
$button = $(button.element); // in "element" stored is reference to the DOM object
text = $button.text() == "ON" ? "OFF" : "ON";
button.attr({
text: text
});
}
}
Note using Highcharts built-in method attr() for updating text, not jQuery's text().
Edit:
For Highcharts 4.2.3+ use the solution below: http://jsfiddle.net/knmb38dy/33/
The only difference is how to get button in jQuery: $button = $(button.element.lastChild).
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.