Create native mobile apps in JavaScript or TypeScript.
BSD-3-CLAUSE License
Bot releases are visible (Hide)
Published by tbuschto about 8 years ago
The WebSockets API is now supported by Tabris.js. This allows to send messages to a server and receive event-driven responses without having to poll the server for a reply.
A new type InactivityTimer
has been added. This timer will elapse after a given period of user inactivity.
var timer = new tabris.InactivityTimer({
delay: 2000
}).on("timeout", function() {
label.set("text", "inactive!");
});
timer.start();
The API of the Video
widget has been extended. You can now hide the player controls with the property controlsVisible
, start and pause a video with the methods play()
and pause()
, and set a position with seek()
.
When a link to a file is selected in the WebView, a download
event will now be fired. This event provides the properties url
, mimeType
, contentLength
and contentDisposition
. The event could be used to trigger a download when a link to an unsupported file type is clicked. This event is only supported on Android.
The new Page property icon
can now be used to set an image on a page header. It is named icon
to prevent a collision with the existing property image
which is used by the PageSelector. It will be renamed in Tabris.js 2.0.
Published by tbuschto about 8 years ago
The CanvasContext object now supports the methods getImageData
, createImageData
and putImageData
.
This new API allows the Tabris.js application to communicate with the HTML document loaded inside a WebView via an HTML5 compatible API. String messages can be exchanged via the postMessage
method and message
event, which are available on the WebView itself and on the window object inside the WebView.
You can now give an additional image to be displayed if the tab is currently selected.
This property can be used to bring up the virtual keyboard by setting it to true
. The user can then immediately start typing.
The Drawer widget now has the events open
and close
, which are fired after the opening/closing animation of the drawer completes.
The widget method "animate" now returns a promise that is resolved when the animation completes, and rejected when the animation is aborted.
In addition to pause
and resume
there are now three new events on the tabris.app
object to react to changes in the app running state: foreground
, background
and terminate
.
The W3C conform global object crypto
has been added. It can be used to generate cryptographically secure random numbers.
In a strictly W3C/browser conform implementation of XMLHttpRequest it is not allowed to access certain headers. Tabris.js no longer implements these restrictions. All headers can now be set and read, including previously "forbidden" headers like "Cookie".
Cordova plugins can now receive permission request callbacks.
To make it easier for everyone to play with their code, we have now made a public Playground available without signing in. Go to tabrisjs.com/playground and scan the QR code with your device using the Tabris.js Developer App. You will see your code in action right away.
Published by tbuschto over 8 years ago
It is now possible to align a given number of CollectionView
cells in a single row, resulting in a grid layout as is common in image galleries or file explorers. The number of columns is controlled via the columnCount
property, with the default 1
representing the traditional list layout.
Control the amount of space between each line of a multi-line TextView
using the property lineSpacing
. The value 1.0
represents the font's default, 2.0
doubles the spacing, and so on.
Using the new tintColor
property you can tint all opaque pixels of an image with the given color. This is useful to represent different states, or just to better align the UI with the platform look & feel.
Since it may take some time to download an image from a remote location, a load
event has been introduced. It fires once the image is visible on screen, or if the image could not be found. Example:
new tabris.ImageView({
image: "http://mycloudstorage/foo.png"
}).on("load", function(imageView, event) {
hidePlaceholder();
if (event.error) {
showFileNotFound();
}
});
Type definitions are now bundled with Tabris.js and can be used without any additional installation. The property and event APIs now provide full auto completion and type information support.
To access type definitions for the promise
and fetch
APIs provided by Tabris.js, their respective type definitions files have to be explicitly referenced in the tsconfig.json
file:
"files": [
"./node_modules/tabris/promise.d.ts",
"./node_modules/tabris/whatwg-fetch.d.ts",
...
]
You can now use Yeoman to create more advanced Tabris.js projects, for example with EcmaScript 6 or TypeScript transpilers already set up.
Simply type:
npm install -g yo generator-tabris-js
yo tabris-js
Published by ralfstx over 8 years ago
Widgets can now be created using their constructors. Instead of tabris.create("Button", { text: "Submit" })
, you can now write:
new tabris.Button({ text: "Submit" });
This syntax is shorter and more common. While tabris.create()
will remain available in all 1.x releases, we encourage you to use constructors from now on. We've also adjusted all our snippets and examples to the new syntax.
In addition to the parent()
children()
methods, widgets now also provide a method siblings()
. This method will return a WidgetCollection
of all widgets that have the same parent, excluding the target widget itself. The method can also be called with a selector expression, which makes it easy to select all siblings of a certain type:
checkbox.on("select", function() {
checkbox.siblings("CheckBox").set("selection", false);
});
The new property cornerRadius
allows you to apply a rounded clipping to the corners of a widget. See the snippet on GitHub.
This property is supported on iOS and Android 5.0+.
The theme used for the system status bar can now be controlled using a new property systemBarTheme
. Possible values are "light"
, "dark"
, and "default"
(which selects the platform default). This property will control the foreground text and icons on the status bar. Note that the light theme will result in a dark foreground and vice-versa. See the snippet on GitHub.
This property is supported on iOS and Android 6+.
As a simpler and more flexible alternative to XmlHttpRequest
, the Fetch API is now available in Tabris.js. The npm module whatwg-fetch
is no longer required.
Tabris.js now includes a full Promise
implementation on all platforms. There is no need to include a promise shim anymore.
Published by ralfstx over 8 years ago
To indicate a pending operation of indeterminate time, you can now use the widget ActivityIndicator
that displays a spinning indicator on both platforms. Have a look at the snippet.
The new property displayMode
on tabris.ui
can be set to "fullscreen"
to enable fullscreen mode, i.e. to hide the system bar. The default display mode is called "normal"
.
The new properties scrollX
and scrollY
can be used to get and to set the current scroll position of a ScrollView
.
In order to prevent the default effect of the back-button on Android, you can now call event.preventDefault()
as a function in your backnavigation
listener. Before you had to set a field of this name to false
. This method is still supported, but discouraged.
Published by ralfstx almost 9 years ago
The TabFolder property tabBarLocation
now accepts the value "hidden"
. Together with paging: true
, this enables a swipe-widget like experience. There's a new snippet for this use case.
Note that the property tabBarLocation
is static, i.e. it can only be set at creation time.
The image
property on Tab
is now also available on Android. You can use it with or without the text
property.
As of Android 5.0, widgets can have an elevation that defines their relative position on the z-axis. The elevation is visually represented by a shadow effect. Transformations now support the additional property translationZ
. While elevation
represents the base state of a widget, the translationZ
property should be altered for animations. Have a look at the new snippets for elevation and translationZ.
Both elevation
and translationZ
are only respected by Android 5.0+.
SearchActions can now be invoked programmatically using the new method open()
.
Published by tbuschto almost 9 years ago
Where the Picker previously only accepted an array of strings it can now deal with any kind of item. This is especially convenient when handling an item in the select
and change:selection
events.
By default the Picker calls toString()
on the item to convert it to string, but you can also provide a custom function to do this in the new itemText
property:
tabris.create("Picker", {
items: airports,
itemText: function(airport) {
return airport.name;
}
});
Just like in ScrollView, CollectionView now has a scroll
event that lets you know when the user has scrolled. The callback contains information about the scrolling direction and distance.
To determine which items are currently visible on screen the firstVisibleIndex
and lastVisibleIndex
properties have been added to CollectionView. These also come with matching change events, which are very well suited to implement an "endless scrolling list". Simply listen to "change:lastVisibleIndex" and start loading more items once the value exceeds a limit of your choosing.
Published by tbuschto about 9 years ago
The iOS client now works on iOS 9.
We provide type definitions to assist you developing Tabris.js apps in TypeScript. See this blog post for details.
In addition to appendTo()
, you can now use the new methods insertBefore()
and insertAfter()
to insert widgets at a given position. This is particularly useful in conjunction with the "prev()"
keyword in layout data.
Switch buttons now offer fine-grained control over colors using the following new properties:
thumbOnColor
thumbOffColor
trackOnColor
trackOffColor
A new method getResourceLocation()
on tabris.app
provides absolute locations for resources that are bundled with the app, such as images, videos, etc.
Published by tbuschto about 9 years ago
In all layout attributes that support referencing other widgets, "prev()"
can now be given (as a string) to refer to the preceding sibling. This is superior to parent.children().last()
or a direct reference for several reasons:
["20%", 10]
it's now also possible to write "20% 10"
.["#foo", 10]
or ["prev()", 10]
, it's now also possible to write "#foo 10"
or "prev() 10"
.All attributes of layoutData
are now also properties of Widget. So if you want to change only a single attribute of layoutData
without affecting the other, simply set the widget property:
widget.set("layoutData", {width: 100, height: 10});
//...
widget.set("left", 100); // width and height do not change
If you wish to set an entirely new layout, use layoutData
:
widget.set("layoutData", {width: 100, height: 10});
//...
widget.set("layoutData": {left: 100}); // width and height are reset
The back button in Android is usually used in Tabris.js to close the current page. However, with the new backnavigation
event on the app
object this behavior can now be overwritten:
tabris.app.on("backnavigation", function(app, options) {
options.preventDefault = true;
// do something else than closing the page
});
To create a "fullscreen" app, simply call tabris.ui.set("toolbarVisible", false);
Note that there is currently a minor issue when using the feature on iOS, see https://github.com/eclipsesource/tabris-js/issues/597.
We have been working on defining a public API that will allow application developer to create their own Tabris.js widgets using JavaScript and Java/Objective-C. The API is neither complete nor final, but already allows creating simple widgets like a Map or Date input.
View all relevant GitHub issues closed in this release here
Published by tbuschto about 9 years ago
Switches are common widgets in mobile UIs. We provide a new widget Switch
with exactly the same API as the existing CheckBox
.
It is now possible to update the JavaScript files and resources of your app without updating the app. See the documentation. The API is considered provisional as we plan to add more functionality to this feature, which may have an impact on the existing API.
It is now possible to use different types of cells (containing different widgets) for different types of data items in a CollectionView. Also, cells may now have different heights depending on the item. Check out the cell types snippet for an example.
Widgets now support the class
property, which is a white-space separated list of labels that can be be used with a class selector (e.g. ".foo"
) in the children
, find
, and apply
methods.
These methods now support additional parameters that will be passed to the callback. These methods are part of the spec, but had not been implemented yet.
The Android client now uses the the appcompat support library, giving Tabris.js apps a consistent material design look and feel across all supported Android versions. It also adds custom theme support.
The Tabris.js online build service now uses Cordova 5.1.1, and supports installing Cordova plug-ins from npm.
View all relevant GitHub issues closed in this release here.
Published by ralfstx over 9 years ago
We think that the name textColor
reflects the purpose of this property better. This property applies to all widgets that display a text.
This property always reflects the index of the data item that is displayed in the cell.
The text
property reflects the current text in the search input field. It also allows to clear the search field. As in the TextInput widget, the message
property allows to insert a hint message into the search field.
We found that chaining animation listeners to the animate method can lead to unexpected behavior. Therefore we decided to remove the return value from the animate method. In future versions, we plan to return a promise object instead.
Instead of a text
property, the Picker widget now provides a property selection
that reflects the currently selected string. The index of the selected item is available in the property selectionIndex
.
In order to listen on changes of a widget's size, use the new resize
event instead of change:bounds
.
Instead of tabris.getContext(canvas, width, height)
, the CanvasContext is now obtained by the getContext
method on the Canvas widget as follows:
ctx = canvas.getContext("2d", widget, height);
The first parameter (contextType) will make it easier for us to provide
HTML5 compatibility without breaking changes.
To extend compatibility with libraries and npm modules that rely on them, the global variables global
and self
are now available. They are aliases for window
and represent the global JavaScript scope.
These are local variables are automatically available in every node module.
We provide them to improve node compatibility.
The field event.target
now always contains the event target. This improves compatibility with some Cordova Plug-Ins.
For widgets and events that have been renamed in previous releases, the old names were still supported as aliases. With this release the old names are no longer supported.
Closing multiple pages by opening a different top-level page did not remove the closed pages from memory. Page handling was largely rewritten, fixing this and several minor page issues.
Published by tbuschto over 9 years ago
Change events ( change:[property]
) are now fired on programmatic changes as well as changes caused by user interaction. Also, they are now fired for all properties, even if the property is not explicitly supported by the widget. The listeners now have three parameters: widget
, newValue
, options
. options
is an object that may be given to the set
method as the last parameter. All change events triggered by that set
will then receive this object. If no options object was given, it will be empty in the change event.
selection
are now select
.submit
is now accept
, and modify
is now input
.selection
or selectionIndex
property now have a select
event. It behaves like change:selection
, but is only fired when the selection
property changes due to user interaction.TextInput
widget now has an input
event. It behaves like change:text
, but is only fired when the text
property changes due to the user typing.Picker
previously fired change:selection
, which should have been change:selectionIndex
. This has been corrected.Published by ralfstx over 9 years ago
Tabris.js now supports gesture events. We recommend using these events instead of the low-level touch events, because the latter can have side effects when used inside scrollable widgets.
The following gesture events are supported:
tap
longpress
pan
pan:left
, pan:right
, pan:up
, pan:down
pan:horizontal
, pan:vertical
swipe:left
, swipe:right
, swipe:up
, swipe:down
Example:
widget.on("swipe:left", function(event) {
moveWidgetLeft();
};
For a more detailed description, see the doc on touch API.
A drawer is a container that can be slid in form the left edge of the screen, often used for navigation. You can now create a drawer yourself by instantiating the type Drawer
. The drawer can be filled with custom content.
var drawer = tabris.create("Drawer");
To display a list of top-level pages, we provide a new type PageSelector
for convenience. The page selector is a collection view that displays all top-level pages and allows to open one of them. It is pre-configured to be easily appendable to the drawer without setting any properties:
tabris.create("Drawer").append(tabris.create("PageSelector"));
For more details on Drawer and PageSelector, see the UI doc.
All Pages, Actions, and the Drawer are now children of the object tabris.ui
. The selector API can be used to obtain them. For example, to get all pages, you can write:
var pages = tabris.ui.children("Page");
The animate()
methods again returns the widget and enables method chaining. The events animationstart
and animationend
are now triggered on the widget itself.
More details can be found in the doc on animation.
Widgets should be positioned by setting the property layoutData
. The property bounds
can be used to obtain the actual position and size of the widget after layouting.
Widgets now have a method isDisposed()
that returns true
when a widget has been disposed.
We decided to rename this widget because the new name fits better into our naming scheme.
Published by ralfstx over 9 years ago
The CollectionView has new methods to modify the items
property. Items can be added and removed using the methods insert
and remove
. For dynamic CollectionViews, please use these new methods instead of setting the items property. When the content of a particular item has changed, the view can be refreshed using the refresh
method. For details, see the reference documentation.
There is a method reveal
that can be used to scroll a given item into view.
The animate()
method now returns an object that can be used to attach listeners to the animation and to cancel it.
A new method apply
allows to set properties on an entire widget hierarchy. This can be used to re-configure the widgets of a page, e.g. in case of an orientation change. It also allows to separate creation and configuration of widgets. Example:
page.apply({
"#userView": {
message: "Email Address",
keyboard: "email",
layoutData: { top: "30%", left: "25%", right: "25%" }
},
"#passView": {
message: "Password",
layoutData: { top: ["#userView", 10], left: "25%", right: "25%" }
},
...
});
A new object tabris.app
represents the running application. This object currently supports events pause
and resume
to observe when the app goes into the background.
A new object tabris.device
provides information on the device. All device information that are provided by Tabris.js itself are accessible on this object. Like Tabris.js widgets, this object has properties that can be accessed with get()
.
The device orientation is available as an additional property orientation
. A change listener for the orientation can be attached. For an example, have a look at the device snippet.
The global device
object now only has those properties that are also available from Cordova device plugin.
Different keyboard types can now be configured for TextInput widgets using the keyboard
property. See also the textinput-keyboard snippet.
Percentages used to be specified as arrays, which was not very readable. Now you can specify percentages as strings, e.g. "25%"
. Percentages can be combined with a fixed offset using an array, e.g. ["25%", 16]
. For an example, have a look at the layout-relative-size snippet.
In addition from the supported properties, you can now also set and get custom properties. The same is true for events. You can attach listeners for a custom event type to any widget and then trigger the event using trigger("my-custom-event")
.
Tabris.js is now available on npm. The dependencies in the package.json
now only require the version number (or a version range). Example:
{
"main": "app.js",
"dependencies": {
"tabris": "0.9.2"
}
}
Published by tbuschto over 9 years ago
The tabris.js
file is now loaded as a regular npm module. This changes the way application declare the Tabris.js version to use. The package.json
should now contain a dependency to tabris.js
. By calling npm install
, the module is installed in the node_modules folder where it can be found by the Tabris.js client.
All widgets support a new property id
that can be set to a custom string. This property will be copied to the field id
. A new method find()
, that is available on all widgets, can be used to find widgets by id. This method accepts filter strings of the form #id
. The method children()
also accepts this kind of filter strings.
When layoutData
attributes refer to other widgets, a string of the form #id
can now be used instead of a widget reference. This reduces the need for keeping widget references in variables.
Some widgets have been renamed:
Label
has been renamed to TextView
, which fits in nicely with ImageView
Text
has been renamed to TextInput
Combo
has been renamed to Picker
The developer console can be activated using the config.xml preferences now. To activate the console the boolean preference EnableDeveloperConsole
was introduced. The default value is false
.
Published by ralfstx over 9 years ago
The pull-to-refresh gesture can be enabled by setting the new property refreshEnabled
on CollectionView
. When enabled, the user can trigger a refresh
event by pulling down. A refresh message can be set using refreshMessage
(iOS only).
For widgets that overlap each other, the z-order is defined by the order in which the widgets are appended to their parent. We've changed the z-order to be more intuitive: new widgets will now be rendered on top of those widgets that have already been appended.
The property maxLines
on Label
can be used to limit the number of lines to be displayed. This approach is preferable to setting a fixed height, as it prevents text lines to be cut off in half.
device.language
contains the device's language as a RFC4747 compatible string (e.g. de_DE
).device.screen.height
and device.screen.width
contain the size of the device's screen in device independent pixel.The events activate
and deactivate
have been introduced for Page
. They're fired when a page is about to become the active page (appear
) and when a page is no longer active (disappear
). They can be used to pause certain tasks when a page becomes inactive and resume them when it becomes active again.
SearchActions are specialized Actions, that shows a search field on activation. Dynamic proposals can be displayed using the property proposals
. In addition to the selection
event, they fire a modify
event on typing in the search field, and a submit
event on submitting a search term.
The new method once
allows to add an event listener to a widget that will be notified only once. The listener will be automatically removed once it has been notified.
initial
.Page.open()
now returns the page itself to enable chaining calls.image
, foreground
, and background
on the tabris.ui
object.Published by ralfstx almost 10 years ago
We've implemented a Node.js / CommonJS compatible module API. To start with the most drastic change, instead of an index.json
file, Tabris.js applications must now contain a package.json
file. This is the standard manifest file that describes a module. This file must contain a field main
that points to the main JavaScript file. You can also use this file to declare dependencies and install them from npm.
If your application consists of multiple files, the main file must include other modules using the require()
function. Modules can export variables using the exports
or module.exports
object. For details, please refer to the Node.js description or have a look at our examples.
We've integrated support for Cordova plug-ins to access device functions. The developer clients have a number of built-in modules. Please have a look at our cordova example. We plan to make it possible to include custom Cordova plug-ins in a Tabris.js application.
In order to support Cordova, we've also improved DOM compatibility by providing common Web API such as the global navigator
object.
visibility
has been renamed to visible
.image
property has been removed from CheckBox
and RadioButton
.ScrollComposite
property scroll
has been renamed to direction
.Action
property placementPriority
accepts only the lower case values (low
, high
, and normal
)Video
widget has been added. See the video snippet for an example.TabFolder
widget has a new property tabBarLocation
to set the position of the tab bar. Supported values are top
, bottom
, and auto
.WebView
widgets supports a new property html
that accepts an entire HTML document.Composite
now supports the events addchild
and removechild
that are fired whenever a new child is added to/removed from a Composite.device
with the properties model
, platform
, and version
.Text
widget supports a new event change:text
that is fired on text modification (i.e. while typing).{url: string}
.transparent
as value. Just like in CSS, this is a synonym for rgba(0, 0, 0, 0)
.children()
accepts a new optional parameter selector
to filter the returned elements (currently only by type).first()
and last()
to access the first/last element.toArray()
, forEach()
, and indexOf()
are also available.We've added checks for property names and values. In case of a misspelled property names or an illegal property value, you should now see a warning in the developer console in most cases.