Create native mobile apps in JavaScript or TypeScript.
BSD-3-CLAUSE License
Bot releases are visible (Hide)
Published by mpost over 5 years ago
The new property trustedCertificates
on the App
objects allows to add a set of certificates to validated SSL connections against. The certificates are applied in addition to the system wide default certificates.
The ArrayBuffer
entries of the trustedCertificates
array consist of the bytes of the certificate files. On Android the certificate file has to be a *.pem (Privacy Enhanced Mail) file whereas on iOS it has to be *.der (Distinguished Encoding Rules) file.
Published by jonek almost 6 years ago
This is intended to be the final 1.x Tabris.js release.
Development continues on master for the upcoming 3.x release.
Maintenance continues for 2.x.
The iOS platform corresponding to this release was updated to allow build artifacts to be published to Apple's app store. Apps built using Tabris.js versions before 1.11.0
are not accepted by Apple anymore.
Otherwise this release does not contain any significant changes compared to v1.10.0.
Published by mpost about 6 years ago
This release addresses bug fixes in the client platforms.
With the added support for linkTap
the TextView
would consume touch events when markupEnabled
would be set to true.
Using an url like ":8080" would crash the app.
Widget was not growing properly when text in the label was wrapped to more than one line.
getImageData
It was possible to perform read operation out of bounds of the array.
enabled
property on delegating switch was not set when setting enabled
on JS side.
Published by tbuschto about 6 years ago
You can now run code in parallel. Not only can that give you a performance boost for CPU intensive tasks, it prevents the UI from becoming unresponsive. The Worker API follows the w3c worker API so it should be very familiar.
const worker = new Worker('worker-add-numbers.js');
worker.onmessage = (event) => {
console.log(`result: ${event.data}`);
worker.terminate();
};
worker.onerror = (error) => {
console.log(`onerror: ${JSON.stringify(error)}`);
worker.terminate();
};
worker.postMessage([number1, number2]);
For Tabris 3.0 we ported the enhanced event API introduced in the tabris-decorators project to the core module. It does not replace the old API, but offers a more convenient, higher level interface especially useful for TypeScript projects and asynchronous programming via async/await.
(async function() {
textView.onTextChanged(handleTextChanged);
textView.text = 'Tap here!';
await textView.onTap.resolve();
textView.text = 'Thank you!';
}());
For Beta 1 we revised many internals to help with future JSX and TypeScript enhancements. A number of APIs have been tweaked for convenience and consistency. Most notably, JSX elements now always need to be imported.
Also, ActionSheet popups can now be created via JSX:
ActionSheet.open(
<ActionSheet title='Actions' onSelect={onSelect} onClose={onClose}>
Select any of the actions below to proceed.
<ActionSheetItem title='Search' image='resources/[email protected]' />
<ActionSheetItem title='Share' image='resources/[email protected]' />
<ActionSheetItem title='Settings' image='resources/[email protected]' />
<ActionSheetItem title='Delete' style='destructive' image='resources/[email protected]' />
<ActionSheetItem title='Cancel' style='cancel' image='resources/[email protected]' />
</ActionSheet>
);
Providing images for high density displays does not require you to give a scale factor explicitly if it can be determined by the file name:
<ActionSheetItem image={{src: 'resources/[email protected]', scale: 3}} />
Can be replaced by this:
<ActionSheetItem image='resources/[email protected]' />
The ScrollView
received a new property to scrollbarVisible
which allows to hide the scrollbars.
Published by mpost about 6 years ago
Published by mpost about 6 years ago
A new selection
property allows to get and set the text cursor position and selection. The selection
is a two element number array representing the text selections start and end position. The native platform usually shows selection handles so that the selection can be changed by the user. A selection
array where both numbers are the same represent a single cursor at the given position. The selection can be observed via the selectionChanged
event as usual.
The new tapLink
event on TextView
fires when the user clicks on a link in an html text. It requires to set markupEnabled
to true and to provide a text containing an anchor (<a>
) with an href
attribute. Eg. textView.text = 'Website: <a href=\"http://example.com>example.com</a>'
. The event object contains a property url
which provides the anchors href
url.
An AlertDialog
can now contain TextInput
widgets to gather user input. The inputs are displayed alongside the title
and message
. The text values inserted by the user can be read in the dialogs close
event from the respective TextInputs
. Eg.: dialog.on('close', (e) => e.target.textInputs[0].text)
.
Published by mpost over 6 years ago
This release fixes two regression discovered in the 2.5.0 release.
Published by tbuschto over 6 years ago
A new Popover
popup has been introduced. It allows to cover the app UI in a modal fashion with a custom UI. On large screen devices the Popover
will be shown in a window style appearance while on small devices it covers the entire screen.
let popover = new Popover();
popover.contentView.append(new TextView({text: 'Hello Popover'}));
popover.open();
The navigationAction
can be used to replace the menu action on the NavigtationView
. This can be useful to e.g. create a custom "close" action.
The background
property on a Widget
now supports linear gradients. The gradient syntax follows the same notation as the W3C linear-gradient
specification.
new Composite({
left: 0, right: 0, top: 0, bottom: 0,
background: 'linear-gradient(to right top, red, green 50%, aqua 150%)',
}).appendTo(tabris.ui.contentView);
All methods that accept selector a string can now also handle child selectors in the CSS-like syntax of 'selectorA > selectorB
. For example:
widget.apply({'.columnLayout > *': {left: 0, top: 'prev() 10', right: 0});
This will apply the given properties to all widgets who's parent has columnLayout
in its class attribute.
The widget find
and apply
methods now also support the selector :host
, inspired by the Web Component API. It always refers to the widget instance of the method that is called. Used with the apply
method it allows a widget to refer to itself or descendants of a specific relationship to itself. Example:
widget.apply({
':host': {left: 0, top: 0, right: 0, bottom: 0},
':host > Composite': {left: 0, top: 'prev() 10', right: 0}
});
Previously this would have required either assigning specific id/class attributes to the targets or separate children
/set
calls.
The StatusBar
supports a new tap
event on iOS. It can be used to e.g. trigger a "scroll-to-top" when the main content of the app consists of a scrolling container.
The new name
property on Device
returns the user provided name of a device, e.g. "Joe's iPhone". The property is supported on iOS only.
The printing capabilities have been extended to print images. An images will be printed fullscreen in the center of the page. To support this new output type a property contentType
has been added to the print options. It has to be either image/<format>
or application/pdf
.
printer.print(data, {jobName: 'image.jpg', contentType: 'image/jpg'}))
.then(event => console.log('Printing finished', event))
.catch(err => console.error(err));
Published by cpetrov over 6 years ago
Published by tbuschto over 6 years ago
prev()
and next()
not working when children()
is overwrittenTextInput
with type password
Published by mpost over 6 years ago
The new widget RefreshComposite
allows to perform the "pull-to-refresh" gesture on a simple layout hierarchy. The API and features are similar to the CollectionView
but the usage is as simple as replacing a regular Composite
with a RefreshComposite
.
The following example lets the RefreshComposite
show activity for 2 seconds.
new RefreshComposite({
left: 0, right: 0, top: 0, bottom: 0,
}).on('refresh', () => setTimeout(({target}) => target.refreshIndicator = false, 2000))
.appendTo(ui.contentView);
Support for native printing has been added via tabris.Printer
. Currently only documents in PDF format are supported.
A Printer
has a method print(..)
which takes the data to print as a ByteArray
and an options object where a jobName
can be provided. A native printing dialog will be shown where additional settings can be applied. The print(..)
method returns a promise which resolves when the print job has been dispatched or throws an error otherwise.
fetch(app.getResourceLocation('resources/example.pdf'))
.then(res => res.arrayBuffer())
.then(data => printer.print(data, {jobName: 'tabris print example'}))
.then(event => console.log('Finished', event))
.catch(err => console.error(err));
A new "pinch-to-zoom" gesture can be used on an ImageView
to magnify an image. To enable the gesture a new property zoomEnabled
along with a zoomLevel
, minZoomLevel
and maxZoomLevel
has been added. The properties also dispatch the expected change events when the user uses a gesture to zoom.
The resting position of a zoomed image is 1.0 with the minZoomLevel
also on 1.0 and the maxZoomLevel
at 3.0.
let imageView = new ImageView({
left: 0, right: 0, top: 0, bottom: 0,
image: 'resources/salad.jpg',
zoomEnabled: true
}).on('zoomChanged', ({value: zoomLevel}) => console.log(zoomLevel)
.appendTo(ui.contentView);
Similar to the keyword prev()
, next()
can be used in a layout declaration. It references the next widget sibling in the parent widget after the current widget.
To close a running app the following call can be made on the tabris.App
. Closing a running app is only supported on Android.
tabris.app.close();
The TextInput
gained two new properties to better integrate into the UI theme and to deal with passwords.
cursorColor
allows to give the cursor a specific color. Only supported on iOS.revealPassword
toggles the visibility of a password inside a TextInput
with type
password. This addition allows to create common sign-in UIs with a checkbox "Show password".The TabFolder
has received new events for tab switching. The appear
event is fired on a Tab
when the tab becomes the selected tab. Complementary, the previously selected Tab
fires the disappear
event.
In case the currently selected Tab
is disposed, the TabFolder
now correctly fires a selectionChanged
event with the newly selected tab as the selection.
Published by cpetrov almost 7 years ago
An API is provided to register a font to use throughout the app. It currently supports TrueType and OpenType fonts.
Tabris.js apps are now displayed in full screen on the iPhone X and widgets have been optimized for the new hardware specifics.
TextInput can now be configured to auto capitalize the first word of a sentence, every word or every letter.
The theme enables customization of the appearance of the navigation bar buttons on devices running Android version 8+.
Published by dbuschtoens almost 7 years ago
To input date or time with native UI elements, a new DateDialog
and TimeDialog
has been added. These dialogs accept listeners which are informed when a new value is picked. To open the DateDialog
the following code can be used:
new DateDialog({
date: new Date()
}).on({
select: ({date}) => console.log(date),
}).open();
To retrieve the devices vendor a new property tabris.device.vendor
has been added. It returns the device manufacturer, e.g.: "Apple" or "Samsung".
Functions that return a WidgetCollection can now be used as JSX elements. As per convention their name has to start with an uppercase letter. The function is called with two arguments: The element's attributes as an object and its children (if any) as an array. An example of this feature would be to call a given widget factory a given number of times:
function Repeat(properties: {times: number}, [callback]: [() => Widget]): WidgetCollection<Widget> {
let result = [];
for (let i = 0; i < properties.times; i++) {
result[i] = callback();
}
return new WidgetCollection(result);
}
It can then be used like a regular element:
ui.contentView.append(
<Repeat times={10}>{() => <textView top='prev() 10'>Hello Again!</textView>}</Repeat>
)
Note that this example assumes that the element has exactly one child (the callback
function), but the type and number of children are not checked at compile time. (The attributes are.) It would therefore be a good idea to check the type of the children at runtime.
When creating a custom subclass of an existing Tabris widget, new properties don't behave the same as the built-in ones out of the box. Getting the constructor as well as the set
and get
methods to accept the new properties has previously been rather tedious. Now, with the with the addition of the tsProperties
property and the Properties
and Partial
interfaces, this process has been greatly simplified.
The following example shows a custom UI component with full support of its new properties:
import {Composite, Partial, Properties} from 'tabris';
class MyCustomForm extends Composite {
public tsProperties: Properties<Composite> & Partial<this, 'foo' | 'bar'>;
// initializing plain properties is a must for "super" and "set" to work as a expected.
public foo: string = null;
public bar: number = null;
constructor(properties?: Properties<MyCustomForm>) {
super(properties);
}
}
Read the section "Interfaces" at EcmaScript 6, TypeScript and JSX for detailed explanations.
Published by cpetrov almost 7 years ago
Issues with console output for thrown errors have been fixed.
Since 2.1.0, the Tabris.js developer app didn't run on iOS 9 anymore. This has been fixed in 2.1.1.
Published by ralfstx about 7 years ago
The app
object has a new method launch()
that accepts a URL and asks the operating system to open this URL in an appropriate external app. Operating systems usually support a variety of URL schemes including http
, https
, mailto
, tel
, and sms
. Apps can also register for custom URL schemes. The method returns a promise to indicate success.
Example:
app.launch('http://tabrisjs.com')
.then(() => console.log('success'))
.catch(err => console.error(err));
The new ActionSheet
allows to show a modal dialog with a set of actions. If many actions are configured the user can scroll the sheet to reveal all actions. The ActionSheet
compliments the existing AlertDialog
when many options with longer text need to be shown. Example:
new ActionSheet({
title: 'Actions',
actions: [
{title: 'Search'},
{title: 'Delete', style: 'destructive'},
{title: 'Cancel', style: 'cancel'},
]
}).on({select: ({index}) => console.log(`${index} selected`)})
.open();
CheckBox and RadioButtons support two new properties tintColor
and checkedTintColor
to set custom tint colors. When only tintColor
is set, it applies to both the checked and the unchecked state. Setting both properties allows for different tint color when checked.
Also the ActivityIndicator can be given a custom tintColor
now.
The console
methods debug()
, log()
, info()
, warn()
, and error()
now use an improved formatting and print different types of values consistently across all platforms. Like the console in Node.js and in web browsers, they now also support printf-like placeholders. Example:
console.log('processed %d items in %d ms', items.length, time);
The new file system API introduced in Tabris.js 2.0 has been extended to support reading and writing of text files and listing directories. The functions remain similar to those known from Node.js except that they return a Promise instead of accepting a callback.
To read a text file, call fs.readFile()
with the encoding in an additional argument. The returned promise will then resolve to a string instead ofreaddir
function, an array buffer:
fs.readFile(path, 'utf-8')
.then(text => console.log('read text from %s:', path, text))
.catch(err => console.error(err));
To write a text file, pass a string instead of an array buffer as second argument to fs.writeFile()
. You can also specify an encoding, if you don't, UTF-8 will be used:
fs.writeFile(path, 'Hello World!', 'ascii')
.then(() => console.log('file written:', path))
.catch(err => console.error(err));
To list the contents of a directory, use the new function fs.readDir()
that returns an array with the names of all files and sub-directories of the given directory, not including '.'
and '..'
. Note that, unlike its equivalent in Node.js, this method name is written in camel case to be consistent with the other functions.
Sometimes, it was necessary to include a wrapper composite just to add some additional white space to a layout. To simplify those layouts, we've added a padding
property to Composite that allows to add space inside the widget's bounds. The padding can either be set to an object with any of the fields left
, right
, top
, and bottom
, or to a single number which would then be applied to all four sides.
new Composite({
padding: {left: 2, right: 2, bottom: 10}
});
The CanvasContext now supports the property font
, allowing you to set the text size, font family, weight and style.
It's now possible register listeners directly in JSX. Any attribute that follows the naming scheme on{EventType}
is used to register a listener with that event. For example:
<button text='Show Message' onSelect={handleButtonSelect}/>
The tabris module now exports the TypeScript interfaces used by the tabris API, including all parameter objects. This is useful when creating your own widgets classes in TypeScript. For details see documentation.
Published by ralfstx over 7 years ago
Improved documentation, snippets and examples.
Last bug fixes.
Published by ralfstx over 7 years ago
Widgets can now be created using JSX syntax. When using TypeScript this requires no extra dependencies, simply generate a new TypeScript project using tabris init
and create a file with the .tsx
file extension. Example:
import {ui} from 'tabris';
ui.contentView.append(
<tabFolder left={0} top={0} right={0} bottom={0}>
<tab title='First tab'>
<textView text='Hello World' />
</tab>
</tabFolder>
);
JSX can be much more expressive than pure JavaScript/TypeScript. Compare the "input" example in JavaScript vs. TypeScript/JSX.
We started to implement a basic filesystem API in Tabris.js. This first version can only read, write, and delete binary files. The API will be extended over time.
The new fs
object provides two properties filesDir
and cacheDir
that point to the base paths for the app. Only files in these directories can be accessed.
The methods writeFile(path, data)
, readFile(path)
, and removeFile(path)
are all asynchronous and return a promise.
Example:
let data = new Uint8Array([1, 2, 3]).buffer;
fs.writeFile(fs.fileDir + '/test.data', data)
.then(() => console.log( data.byteLength + ' bytes written'))
.catch(err => console.error(err));
See the documentation for the details.
To attach custom data to a Widget without the risk of clashes with widget internals, you can now use the data
property. This property holds an empty object that is not used by the framework and can be freely used by the application code. Manipulations on this object will not affect the widget itself. Example:
widget.data.myItem = 23;
We introduced a new method load()
in CollectionView that replaces the current items with a new ones. To load new data into a CollectionView, use this method instead of setting the itemCount
property.
The pages()
method on NavigationView now accepts a selector argument similar to children()
to filter the list of pages. Example:
navigationView.pages('.temporary').dispose();
The color of the indicator in Slider and ProgressBar widgets can now be controlled by the new property tintColor
. This had been possible with textColor
, which is no longer supported on these widgets.
tabris.app
events background
, foreground
, pause
and resume
. terminate
will not be supported in the foreseeable future.tabris.app
properties appID
, version
and versionID
.tabris.CollectionView
property cellType
, and support for automatic itemHeight
.tabris.CollectionView
method reveal
tabris.AlertDialog
. The neutral
button is not yet supported.WebSocket
.background
is now applied only to the tab bar, as on Android.textColor
will not be supported in the foreseeable future.win_tabBarTheme
allows setting the windows dark/light theme on the tab bar only.When you build your Tabris 2.0 app with the online build service at tabrisjs.com, this build will now use the Tabris CLI. As a notable difference to 1.x, apps that built in debug mode won't be wrapped in a developer app anymore. You can load a remote app using the new URL field in the developer console. Also note that the developer console must be enabled explicitly in your config.xml
, e.g.:
<preference name="EnableDeveloperConsole" value="$IS_DEBUG" />
Published by ralfstx over 7 years ago
With this first release candidate, we've finalized the API for Tabris.js 2.0.
The CollectionView has a new API based on item indexes instead of the items itself. This gives the developer more control over binding different types of models to a CollectionView.
The items
property has been replaced by a new property itemCount
that controls the number of items to be displayed. To add or remove items at runtime, the methods insert()
and remove()
can be used, however, insert()
now expects and item count instead of an array.
The cells of a CollectionView must now be created by the application in the callback createCell
, which replaces the initializeCell
callback. Any type of widget can be used as a cell. The type Cell has become obsolete and was removed. Example:
function createCell(type) {
return new TextView({
font: type === 'header' ? 'bold 18px' : '14px'
});
}
Instead of the change:item
event, the cells are now populated in a dedicated updateCell
callback that receives the cell view and the item index to show:
function updateCell(cell, index) {
cell.text = items[index].name;
}
The property itemHeight
has been renamed to cellHeight
for consistency. This property now also supports the value 'auto'
that will calculate the height of each cell individually.
Since the CollectionView now works on item count and indexes instead of an array of items, the Picker API now follows the same approach.
The property items
has been replaced by itemCount
. The property selection
that accepted the selected item has been removed in favor of the existing property selectionIndex
.
The itemText
callback is now required to provide a text for a given item. This callback is now called with an index instead of an item.
Removing hidden pages from a NavigationView using detach()
or dispose()
does no longer auto-remove pages stacked on top of the removed page. This allows you to remove underlying pages and so to change the target for back navigation.
The height of the toolbar(s) is now available as read-only properties topToolbarHeight
and bottomToolbarHeight
.
To prepare for pre-configured page transitions, the property animated
has been replaced by a property pageAnimation
that accepts the values 'default'
and 'none'
.
The WebView now supports navigating in the history using the new methods goBack()
and goForward()
. To check if this navigation is currently possible, you can use the read-only properties canGoBack
and canGoForward
.
The new property enterKeyType
on TextInput
allows to specify the label or icon shown on the return key of the keyboard. Supported values are 'default'
, 'done'
, 'next'
, 'send'
, 'search'
, and 'go'
.
All-lowercase event names and those with a colon in their name (such as pan:left
) have been renamed to camelCase (e.g. panLeft
). This affects the following events:
pan:
and swipe:
.close
event on AlertDialog
have been renamed from close:ok
, close:cancel
and close:neutral
to closeOk
, closeCancel
, and closeNeutral
.addchild
and removechild
are now addChild
and removeChild
.touchStart
, touchEnd
, touchCancel
and touchMove
.change:text
) are now named after the pattern <property>Changed
. For example, the event change:text
becomes textChanged
.Pan events now have separate properties for translationX
and translationY
instead of translation
to match with the properties of the Widget's transform
object. The property velocity
has been replaced by individual properties velocityX
and velocityY
.
The methods on()
, off()
, and once()
now also support maps of events and listeners to allow adding and removing multiple listeners in a single statement. Example:
new CheckBox({
left: 12, top: 12
}).on({
tap: onTap,
select: onSelect
}).appendTo(parent);
This version of these methods also offer improved typing and tool support.
Besides the target
property, all events now include the additional properties type
(the event name) and timeStamp
(the event timestamp in milliseconds). The latter replaces the property time
on touch events.
As all listeners now receive an event object, the trigger()
method also expects an object as second parameter and does not delegate additional parameters to the listeners anymore.
Instead of using a polyfill, a subset of the fetch API is now implemented in Tabris.js directly. With this change, the response objects now include the method arrayBuffer()
to allow downloading binary content using fetch:
fetch(url).then(response => response.arrayBuffer()).then(buffer => ...)
As an addition to the standard, this implementation also features a timeout
option:
fetch(url, {
timeout: 5000 // request timeout in ms
}).then(...);
Color properties now accept colors in the format #rrggbbaa
where the aa
part defines the alpha channel (opacity) as hex value between 00
(transparent) and ff
(opaque).
For those who like to try out the latest developments in tabris, nightly builds are now available on npm. You can install the latest nightly using npm install tabris@nightly
or include a dependency like this:
"dependencies": {
"tabris": "nightly"
}
Published by ralfstx over 7 years ago
We've redesigned the API for event listeners. All event listeners now receive a single event object instead of separate parameters. This change requires adjustments to all existing applications, however, it will allow us to add new event properties over time without introducing any more breaking changes.
All event objects have a target
property that references the object that received the event. All change listeners (change:property
) include a property value
that contains the new value of the changed property. Other properties are specific to the event type.
For example, an event listener for a checkbox would now look like this:
checkbox.on('select', (event) => {
event.target // the checkbox that received the event
event.checked // the checked state
});
Please refer to the documentation for the properties available on the respective events. You may also want to look at the updated snippets.
On all stateful button widgets, that is CheckBox
, RadioButton
, ToggleButton
, and Switch
, the property selection
has been renamed to checked
. The select
event also contains a parameter checked
that reflects the new state.
On touch events, the properties pageX
and pageY
have been renamed to absoluteX
and absoluteY
, respectively. These properties reflect the position relative to the content view (ui.contentView
).
The events animationstart
and animationend
have been removed in favour of the new Promise API. Those events were hard to consume as they could fire before the listener was even attached and they weren't specific to a certain animation. With the Promise returned by the animate()
method, it has become much easier to perform actions on completion. Example:
widget.animate({opacity: 0}, {duration: 300, easing: 'ease-out'}).then(() => widget.dispose());
Tabris.js can now create Windows 10 Store apps for desktop, tablet and phone. Not all APIs will be supported on the launch of Tabris.js 2.0, so keep an eye on the Windows 10 support article of the Tabris.js documentation. For now Tabris Connect can build appxbundle
files suitable for sideloading, appxupload
files for store deployment will be available at launch.
The latest version of tabris-cli supports building apps on your local machine by calling
tabris build [android|ios|windows]
The interface for custom widgets has changed. If you've developed a native custom widget, please refer to the custom widget documentation for the new API.
To facilitate the migration of existing apps, we've created a migration guide.
Published by ralfstx over 7 years ago
Tabris.js does not dictate the use of pages anymore. Widgets can be added directly to the main area of the app.
The object tabris.ui
, which represents the UI root, now has a number of children, that represent different parts of the app's user interface:
tabris.ui.statusBar
- shows the time and some system status iconstabris.ui.navigationBar
- contains the Back, Home, etc. buttons on Androidtabris.ui.contentView
- contains the app's main UItabris.ui.drawer
- can be swiped in from the leftWidgets can be appended to contentView
, and optionally to the drawer
:
new tabris.Button({
left: 16, top: 16
}).appendTo(tabris.ui.contentView);
There's only a single drawer widget available as tabris.ui.drawer
. The type tabris.Drawer
cannot be instantiated anymore. The drawer is disabled by default, to use it in an application, you have to enable it:
tabris.ui.drawer.enabled = true;
The new widget NavigationView
offers page-based navigation. By creating multiple instances of this widget, it is now possible to have multiple page stacks in an app, for example in different tabs.
Pages are now appended to and removed from a NavigationView using the standard widget methods append()
, appendTo()
, detach()
, and dispose()
, respectively. When a page is added, it becomes the topmost page on the page stack and covers any previous page. The methods open()
and close()
on Page are obsolete and have been removed.
On back navigation, the topmost page will be disposed. When a page is removed from a NavigationView, all pages on top will be disposed automatically. To prevent pages from being automatically disposed, you can set the property autoDispose
to false
. The property topLevel
has also been removed.
The header of a NavigationView can be styled using the new properties toolbarColor
, actionColor
, titleTextColor
, and actionTextColor
.
Actions and SearchActions are now also added to instances of a NavigationView.
The helper type PageSelector
, that showed a list of pages did not fit with the new UI model that allows for multiple page stacks. It has been removed.
The new type AlertDialog
can be used to display modal dialogs to the user. An alert dialog can contain a message text and up to three buttons with custom texts.
The ScrollView
properties offsetX
and offsetY
are now read-only. To scroll programmatically, use the methods scrollToX()
and scrollToY()
. You can omit the animation by adding {animate: false}
as second parameter.
A new property tabMode
on TabFolder
allows to enable overflow behavior on Android. It can be set to 'fixed'
(default) or 'scrollable'
. When set to 'scrollable'
, the tabs in the tab bar will overflow and can be scrolled.
A new TabFolder event scroll
is fired when paging
is enabled and a tab is scrolled. This event can be used to implement transition effects such as parallax scrolling.
With a new property selectable
on TextView
, you can allow copying from a TextView into the clipboard. This property is currently only support on Android.
A new property keepFocus
has been introduced on TextInput
. When set to true
the TextInput
will keep its focus, even when tapped outside of the widget bounds, thereby leaving the keyboard open.
The new properties fillColor
and borderColor
provide more fine-grained control over the look and feel of TextInput
and Picker
widgets.
Data URIs can now be used in all widget properties that accept an image.
The read-only properties id
, version
, and versionCode
on tabris.app
provide information on the app id and version.
The responseType
'arraybuffer'
is now supported by the XHR implementation in Tabris.js and supports downloading binary content.
A new property pinnedCertificate
on tabris.app
can be used to enable certificate pinning.
The property accepts an array of pinned certificates in the form of
[
{host: <string>, hash: <string>, algorithm: <RSA2048|RSA4096|ECDSA256>},
...
]
You can now access all widget properties directly, without using get()
and set()
:
button.text = 'OK';
var text = button.text;
The methods get()
and set()
remain available.
In Tabris 1.0, calling a widget's off()
method with zero arguments could be used to remove all listeners from a widget and off(topic)
to remove all listeners for a given event topic. As these calls could affect other modules, they were considered risky and have been removed.
Tabris widgets can be created without a parent and appended to a parent later. Using appendTo()
they can be re-parented. A new method detach()
now allows to remove a widget from its current parent for later re-use.
You can use the new method includes()
to find out whether a widget exists in a collection, e.g.
if (parent.children().includes(widget)) {
...
}
The method tabris.registerWidget
that had been recommended for custom widgets has been removed. Native widgets should now extend Widget
. We recommend to use ES6 classes and transpile the code as needed.
class MyWidget extends Widget {
get foo() {}
set foo(value) {}
...
}
A new Android specific image url scheme android-drawable
allows to load bundled resource drawables, e.g. new tabris.ImageView({image: 'android-drawable://ic_icon' })
. The bundled resources have to be placed in their respective drawable folders during app build time.
The cordova build now supports to configure a splash screen via the <splash ..>
element. To customize the theme extend one of the SplashScreen themes.
DarkActionBar
to DarkAppBar
theme
now expects a theme resource id instead of a qualified class name