source: trunk/doc/src/declarative/javascriptblocks.qdoc@ 1036

Last change on this file since 1036 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 11.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the documentation of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:FDL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in a
14** written agreement between you and Nokia.
15**
16** GNU Free Documentation License
17** Alternatively, this file may be used under the terms of the GNU Free
18** Documentation License version 1.3 as published by the Free Software
19** Foundation and appearing in the file included in the packaging of this
20** file.
21**
22** If you have questions regarding the use of this file, please contact
23** Nokia at [email protected].
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29\page qdeclarativejavascript.html
30\title Integrating JavaScript
31
32QML encourages building UIs declaratively, using \l {Property Binding} and the
33composition of existing \l {QML Elements}. To allow the implementation of more
34advanced behavior, QML integrates tightly with imperative JavaScript code.
35
36The JavaScript environment provided by QML is stricter than that in a web browser.
37In QML you cannot add, or modify, members of the JavaScript global object. It
38is possible to do this accidentally by using a variable without declaring it. In
39QML this will throw an exception, so all local variables should be explicitly
40declared.
41
42In addition to the standard JavaScript properties, the \l {QML Global Object}
43includes a number of helper methods that simplify building UIs and interacting
44with the QML environment.
45
46\section1 Inline JavaScript
47
48Small JavaScript functions can be written inline with other QML declarations.
49These inline functions are added as methods to the QML element that contains
50them.
51
52\code
53Item {
54 function factorial(a) {
55 a = parseInt(a);
56 if (a <= 0)
57 return 1;
58 else
59 return a * factorial(a - 1);
60 }
61
62 MouseArea {
63 anchors.fill: parent
64 onClicked: console.log(factorial(10))
65 }
66}
67\endcode
68
69As methods, inline functions on the root element in a QML component can be
70invoked by callers outside the component. If this is not desired, the method
71can be added to a non-root element or, preferably, written in an external
72JavaScript file.
73
74\section1 Separate JavaScript files
75
76Large blocks of JavaScript should be written in separate files. These files
77can be imported into QML files using an \c import statement, in the same way
78that \l {Modules}{modules} are imported.
79
80For example, the \c {factorial()} method in the above example for \l {Inline JavaScript}
81could be moved into an external file named \c factorial.js, and accessed like this:
82
83\code
84import "factorial.js" as MathFunctions
85Item {
86 MouseArea {
87 anchors.fill: parent
88 onClicked: console.log(MathFunctions.factorial(10))
89 }
90}
91\endcode
92
93Both relative and absolute JavaScript URLs can be imported. In the case of a
94relative URL, the location is resolved relative to the location of the
95\l {QML Document} that contains the import. If the script file is not accessible,
96an error will occur. If the JavaScript needs to be fetched from a network
97resource, the component's \l {QDeclarativeComponent::status()}{status} is set to
98"Loading" until the script has been downloaded.
99
100Imported JavaScript files are always qualified using the "as" keyword. The
101qualifier for JavaScript files must be unique, so there is always a one-to-one
102mapping between qualifiers and JavaScript files. (This also means qualifiers cannot
103be named the same as built-in JavaScript objects such as \c Date and \c Math).
104
105
106\section2 Code-Behind Implementation Files
107
108Most JavaScript files imported into a QML file are stateful, logic implementations
109for the QML file importing them. In these cases, for QML component instances to
110behave correctly each instance requires a separate copy of the JavaScript objects
111and state.
112
113The default behavior when importing JavaScript files is to provide a unique, isolated
114copy for each QML component instance. The code runs in the same scope as the QML
115component instance and consequently can can access and manipulate the objects and
116properties declared.
117
118\section2 Stateless JavaScript libraries
119
120Some JavaScript files act more like libraries - they provide a set of stateless
121helper functions that take input and compute output, but never manipulate QML
122component instances directly.
123
124As it would be wasteful for each QML component instance to have a unique copy of
125these libraries, the JavaScript programmer can indicate a particular file is a
126stateless library through the use of a pragma, as shown in the following example.
127
128\code
129// factorial.js
130.pragma library
131
132function factorial(a) {
133 a = parseInt(a);
134 if (a <= 0)
135 return 1;
136 else
137 return a * factorial(a - 1);
138}
139\endcode
140
141The pragma declaration must appear before any JavaScript code excluding comments.
142
143As they are shared, stateless library files cannot access QML component instance
144objects or properties directly, although QML values can be passed as function
145parameters.
146
147
148\section2 Importing One JavaScript File From Another
149
150If a JavaScript file needs to use functions defined inside another JavaScript file,
151the other file can be imported using the \l {QML:Qt::include()}{Qt.include()}
152function. This imports all functions from the other file into the current file's
153namespace.
154
155For example, the QML code below left calls \c showCalculations() in \c script.js,
156which in turn can call \c factorial() in \c factorial.js, as it has included
157\c factorial.js using \l {QML:Qt::include()}{Qt.include()}.
158
159\table
160\row
161\o {1,2} \snippet doc/src/snippets/declarative/integrating-javascript/includejs/app.qml 0
162\o \snippet doc/src/snippets/declarative/integrating-javascript/includejs/script.js 0
163\row
164\o \snippet doc/src/snippets/declarative/integrating-javascript/includejs/factorial.js 0
165\endtable
166
167Notice that calling \l {QML:Qt::include()}{Qt.include()} imports all functions from
168\c factorial.js into the \c MyScript namespace, which means the QML component can also
169access \c factorial() directly as \c MyScript.factorial().
170
171
172\section1 Running JavaScript at Startup
173
174It is occasionally necessary to run some imperative code at application (or
175component instance) startup. While it is tempting to just include the startup
176script as \e {global code} in an external script file, this can have severe limitations
177as the QML environment may not have been fully established. For example, some objects
178might not have been created or some \l {Property Binding}s may not have been run.
179\l {QML JavaScript Restrictions} covers the exact limitations of global script code.
180
181The QML \l Component element provides an \e attached \c onCompleted property that
182can be used to trigger the execution of script code at startup after the
183QML environment has been completely established. For example:
184
185\code
186Rectangle {
187 function startupFunction() {
188 // ... startup code
189 }
190
191 Component.onCompleted: startupFunction();
192}
193\endcode
194
195Any element in a QML file - including nested elements and nested QML component
196instances - can use this attached property. If there is more than one \c onCompleted()
197handler to execute at startup, they are run sequentially in an undefined order.
198
199Likewise, the \l {Component::onDestruction} attached property is triggered on
200component destruction.
201
202
203\section1 Property Assignment vs Property Binding
204
205When working with both QML and JavaScript, it is important to differentiate between
206QML \l {Property Binding} and JavaScript value assignment. In QML, a property
207binding is created using the \e {property: value} syntax:
208
209\code
210Rectangle {
211 width: otherItem.width
212}
213\endcode
214
215The \c width of the above \l Rectangle is updated whenever \c otherItem.width changes. On the other
216hand, take the following JavaScript code snippet, that runs when the \l Rectangle is created:
217
218\code
219Rectangle {
220
221 Component.onCompleted: {
222 width = otherItem.width;
223 }
224}
225\endcode
226
227The \c width of this \l Rectangle is \e assigned the value of \c otherItem.width using the
228\e {property = value} syntax in JavaScript. Unlike the QML \e {property: value} syntax, this
229does not invoke QML property binding; the \c rectangle.width property is set to the value
230of \c otherItem.width at the time of the assignment and will not be updated if that value
231changes.
232
233See \l {Property Binding} for more information.
234
235
236\section1 Receiving QML Signals in JavaScript
237
238To receive a QML signal, use the signal's \c connect() method to connect it to a JavaScript
239function.
240
241For example, the following code connects the MouseArea \c clicked signal to the \c jsFunction()
242in \c script.js:
243
244\table
245\row
246\o \snippet doc/src/snippets/declarative/integrating-javascript/connectjs.qml 0
247\o \snippet doc/src/snippets/declarative/integrating-javascript/script.js 0
248\endtable
249
250The \c jsFunction() will now be called whenever MouseArea's \c clicked signal is emitted.
251
252See \l {Connecting signals to methods and other signals} for more information.
253
254
255\section1 QML JavaScript Restrictions
256
257QML executes standard JavaScript code, with the following restrictions:
258
259\list