summaryrefslogtreecommitdiffstats
path: root/doc/src/declarative/javascriptblocks.qdoc
blob: c2d63b2912c103dbc16070eda870641d936d3b65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
\page qmljavascript.html
\title JavaScript Blocks

QML encourages building UIs declaratively, using \l {Property Binding} and the 
composition of existing \l {QML Elements}.  If imperative code is required to implement 
more advanced behavior, the \l Script element can be used to add JavaScript code directly 
to a QML file, or to include an external JavaScript file.

The \l Script element is a QML language \e intrinsic.  It can be used anywhere in a
QML file, \e except as the root element of a file or sub-component, but cannot be 
assigned to an object property or given an id.  The included JavaScript is evaluated 
in a scope chain.  The \l {QML Scope} documentation covers the specifics of scoping 
in QML.  

A restriction on the JavaScript used in QML is that you cannot add new members to the
global object. This happens transparently when you try to use a variable without
declaring it, and so declaring local variables is required when using Java script in
QML.

The global object in QML has a variety of helper functions added to it, to aid UI
implementation. See \l{QML Global Object} for further details.

Note that if you are adding a function that should be called by external elements,
you do not need the \l Script element. See \l {Extending types from QML#Adding new methods}
{Adding new methods} for information about adding slots that can be called externally.

\section1 Inline Script

Small blocks of JavaScript can be included directly inside a \l {QML Document} as
the body of the \l Script element.

\code
Rectangle {
    Script {
        function factorial(a) {
            a = Integer(a);
            if (a <= 0)
                return 1;
            else 
                return a * factorial(a - 1);
        }
    }
}
\endcode

Good programming practice dictates that only small script snippets should be written 
inline.  QML prohibits the declaration of anything other than functions in an inline
script block.  For example, the following script is illegal as an inline script block 
as it declares the non-function variable \c lastResult.

\code
// Illegal inline code block
var lastResult = 0
function factorial(a) {
    a = Integer(a);
    if (a <= 0) 
        lastResult = 1;
    else 
        lastResult = a * factorial(a - 1);
    return lastResult;
}
\endcode

\section1 Including an External File

To avoid cluttering the QML file, large script blocks should be in a separate file.
The \l Script element's \c source property is used to load script from an external
file.

If the previous factorial code that was illegal as an inline script block was saved
into a "factorial.js" file, it could be included like this.

\code
Rectangle {
    Script { 
        source: "factorial.js"
    }
}
\endcode

The \c source property may reference a relative file, or an absolute path.  In the
case of a relative file, the location is resolved relative to the location of the
\l {QML Document} that contains the \l Script element.  If the script file is not 
accessible, an error will occur.  If the source is on a network resource, the
enclosing QML document will remain in the \l {QmlComponent::status()}{waiting state}
until the script has been retrieved.

\section1 Running Script at Startup

It is occasionally necessary to run a block of JavaScript code at application (or
component instance) "startup".  While it is tempting to just include the startup
script as \e {global code} in an external script file, this can have severe limitations
as the QML environment may not have been fully established.  For example, some objects 
might not have been created or some \l {Property Binding}s may not have been run.
\l {QML Script Restrictions} covers the exact limitations of global script code.

The QML \l Component element provides an \e attached \c onCompleted property that
can be used to trigger the execution of script code at startup after the
QML environment has been completely established.

The following QML code shows how to use the \c Component::onCompleted property.

\code
Rectangle {
    Script {
        function startupFunction() {
            // ... startup code
        }
    }

    Component.onCompleted: startupFunction();
}
\endcode

Any element in a QML file - including nested elements and nested QML component 
instances - can use this attached property.  If there is more than one script to
execute at startup, they are run sequentially in an undefined order.

\section1 QML Script Restrictions

QML \l Script blocks contain standard JavaScript code.  QML introduces the following
restrictions.

\list
\o Script code cannot modify the global object.

In QML, the global object is constant - existing properties cannot be modified or 
deleted, and no new properties may be created.

Most JavaScript programs do not explicitly modify the global object.  However, 
JavaScript's automatic creation of undeclared variables is an implicit modification
of the global object, and is prohibited in QML.

Assuming that the \c a variable does not exist in the scope chain, the following code 
is illegal in QML.

\code
// Illegal modification of undeclared variable
a = 1;
for (var ii = 1; ii < 10; ++ii) a = a * ii;
    console.log("Result: " + a);
\endcode

It can be trivially modified to this legal code.

\code
var a = 1;
for (var ii = 1; ii < 10; ++ii) a = a * ii;
    console.log("Result: " + a);
\endcode

Any attempt to modify the global object - either implicitly or explicitly - will 
cause an exception.  If uncaught, this will result in an warning being printed, 
that includes the file and line number of the offending code.

\o Global code is run in a reduced scope

During startup, if a \l Script block includes an external file with "global"
code, it is executed in a scope that contains only the external file itself and
the global object.  That is, it will not have access to the QML objects and 
properties it \l {QML Scope}{normally would}.

Global code that only accesses script local variable is permitted.  This is an 
example of valid global code.

\code
var colors = [ "red", "blue", "green", "orange", "purple" ];
\endcode

Global code that accesses QML objects will not run correctly.

\code
// Invalid global code - the "rootObject" variable is undefined
var initialPosition = { rootObject.x, rootObject.y }
\endcode

This restriction exists as the QML environment is not yet fully established.  
To run code after the environment setup has completed, refer to 
\l {Running Script at Startup}.

\endlist

*/