/**************************************************************************** ** ** 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 */