~~Title: Javascript Tutorial~~ ==== Javascript Tutorial ==== This Javascript tutorial describes the basic steps to compile and run a Javascript example using EFL with Node.Js The Javascript bindings are currently in BETA state. === Prerequisite === Before you start you may want to read about how to compile the EFL: * Installed from source: [[develop/efl/start|Get started with EFL]]. === Dependencies === You will need additional dependencies to Javascript Bindings: * [[https://nodejs.org|node]] (4.2 or higher) === Compilation === == Efl == To configure efl sources with nodejs bindings add ''//––with-js=nodejs//'' to the configure flags: ./configure --with-js=nodejs #in efl source path After that, you can compile normally with: make make install === Node.Js === EFL will install its nodejs modules - named ''efl.node'' - under the ''/lib'' path. The default prefix, if not explicitly defined, is ''/usr/local''. In order to nodejs discover these modules, add the previously cited folder to the ''NODE_PATH'' environment variable: export NODE_PATH=/usr/local/lib:$NODE_PATH #if necessary replace with your prefix path To check if the path is correctly set, use ''require'' inside nodejs to import the module: ~$ node > efl = require("efl") ====Button Example==== You can find this example in ''/src/examples/elementary/button_example_00.js'' Import Efl module efl = require('efl'); Create a new Window with //auto hide// (the window is automatically hidden when the close button is clicked): win = new efl.Efl.Ui.Win.Standard(null); win.setText("Hello, World!"); // Sets the title win.setAutohide(true); Create a new Button (passing the newly created window as parent) and set new label text to button: btn = new efl.Elm.Button(win); btn.setText(null, "Good-Bye, World!"); Set button basic size and positions: btn.setSize(120, 30); btn.setPosition(60, 15); btn.setHintWeight(1.0, 1.0); btn.setHintAlign(1.0, 1.0); The method ''on'' is used to register callback on events. In this case we need to catch the ''clicked'' event, so we register a function (second argument) to print a log message when the button ''btn'' is clicked: btn.on('clicked', function () { console.log('clicked'); } ); To finish, it is necessary to show all elements, using the ''setVisible(true)'' method: btn.setVisible(true); win.setSize(240, 60); win.setVisible(true); Once finished this setup, the ''efl.node'' module automatically integrates with the nodejs main loop without requiring you to call it explicitly. ====Twitter Example==== You can find the complete twitter example in ''/src/examples/twitter_example_01.js'' This is a more complex example, with edje theming and some external requirements. We need to install the ''request'' and ''twitter'' nodejs modules, using the ''npm'' (node.js package manager) to automatically download and install all necessary files: npm install request npm install twitter ''npm'' is installed by default with Node.js Import all modules and initialize the necessary variables to connect to the twitter API efl = require('efl'); // Standard node modules util = require('util'); fs = require('fs'); path = require('path'); // 3rd pardy modules, requiring install with npm request = require('request'); //need "npm install request" twitter = require('twitter'); //need "npm install twitter" // Twitter access keys var twit = new twitter({ consumer_key: 'ZbSM93w5Sp2cyZ2SG0XuCvoHV', consumer_secret: 'g8N7EEQLpdKPnAsS9hWuQV29FYjBkhH62jhZzXyYymDw87DKye', access_token_key: '222611263-pPhKKjYh59uuNLP0b86sP7aAtLhdecjVQaEsCDCv', access_token_secret: 'l7ccNKXTVv6cymfSD1gQH61tmfixkdna2QmOjPtpVxSHD' }); user_acount = 'EnlightenmentKo' // our target twitter account to be shown Create a new Window (as in the previous example): win = new efl.Efl.Ui.Win.Standard(null); win.setText("Twitter App"); win.setAutohide(true); Create and show two //boxes// widget containers, one to be the top level box and another to work like a list, with the individual tweets. box = new efl.Efl.Ui.Box(win); box.setHintWeight(1.0, 1.0); win.setContent(box); box.setVisible(true); tweet_box = new efl.Efl.Ui.Box(win); tweet_box.setHintWeight(1.0, 1.0); tweet_box.setHintAlign(-1.0, -1.0); tweet_box.setPackPadding(0.0, 30.0, true); // Give some space between the tweets box.packEnd(tweet_box); The default box orientation is horizontal. In order to resemble the original timeline appearance, we need to make it horizontal. This is made in two steps, first we "cast" the box to an ''Efl.Orientation'' object and then we actually set the orientation. This explicit cast is currently required as ''Efl.Ui.Box'' inherits from both ''Elm.Widget'' and the interface ''Efl.Orientation''. These two classes/interfaces define a method called ''setOrientation''. In C you can specify which one you want by calling the respective function, e.g. ''elm_widget_orientation_set'' or ''efl_orientation_orientation_set''. In the Javascript bindings, the current approach is using these explicit casts. tweet_box_orient = tweet_box.cast("Efl.Orientation"); tweet_box_orient.setOrientation(efl.Efl.Orient.VERTICAL); Now we are ready to ask the twitter module to get the timeline of the target user. The 'get' function will be passed a callback that will be called when the data is ready. Inside it, we will start building the tweet list. Also, we create an array to store the icon widgets to be filled when the icon finish downloading. icon_array = new Array(); // To store the icons twit.get('statuses/user_timeline', {screen_name: user_acount, count:10}, function(error, tweets, response) { if (error) return; // Begin building the tweets For each tweet, we make a new ''Elm.Layout'' and set various components, or, in efl jargon, "parts", using the ''set*'' family of methods. First, we set a base theme using ''setFile''. The layout will load the given file and setup the internal layout structure, etc. This will allow us to refer the individual tweet's parts by name on the following methods. The edj file used was compiled from a source edc file. For more information, see the next section. // continuing the previous callback for(i=0; i < tweets.length; i++){ // extract the data we got from the twitter api var user_name = tweets[i].user.name; var screen_name = tweets[i].user.screen_name; var text = tweets[i].text; var layout = new efl.Elm.Layout(win); // Use __dirname to get the file from the same folder of this .js var filename = path.join(__dirname, "twitter_example_01.edj"); layout.setFile(filename, "tweet"); // Load the 'tweet' group from theme file Once we have the theme loaded, we can use ''setText'' to set a new text to the related Edje parts in the theme, referring them on each call by using the name of the part as the first argument. // Continuing the previous for loop layout.setText("user_name", screen_name); layout.setText("screen_name", " - @"+screen_name); To have a formatted text, we use an ''Elm.Entry'' to show the main tweet text and add this widget into the theme using the ''setContent'' layout method. This allows us to inject full widgets into the layout, besides the basic stuff. Like ''setText'', ''setContent'' also receives the name of the target part as the first argument. // continuing the previous for loop var entry = new efl.Elm.Entry(win); entry.setText("elm.text", text); entry.setEditable(false); // We have to cast to the proper type, like in the previous box orientation // case part = layout.part("tweet_text").cast("Efl.Container"); part.setContent(entry); // Some sizing details for better looking layout.setHintMin(127, 96); layout.setHintWeight(1.0, 1.0); layout.setHintAlign(-1.0, -1.0); Now, for the icon, we use an ''efl.Efl.Ui.Image''. It'll be set to display the downloaded icon. Like the entry above, it will be placed in a swallow part of the theme. // continuing the for loop var icon = new efl.Efl.Ui.Image(win); icon.fillInside = true; icon_array.push(icon); user_icon = layout.part("user_icon").cast("Efl.Container"); user_icon.setContent(icon); // Pack the tweet into the box. item = tweet_box.packEnd(layout); layout.setVisible(true); } // Finished the for loop To show the tweet image, we need to download it. We can accomplish this creating a new file stream with ''fs.createWriteStream'' and download the image to this file stream using the ''request'' module. Once the download is finished, we iterate through the list of icons widgets and tell them to display the downloaded file. We also tell the tweet box and the window to show themselves. if (tweets.length > 0) { var icon_filename = '/tmp/twitter_pic.jpg'; var file = fs.createWriteStream(icon_filename); file.on('finish', function() { console.log("finished loading the icon file."); for (i=0; i < icon_array.length; i++) { icon_array[i].setFile(icon_filename, null); } }); request(tweets[0].user.profile_image_url).pipe(file); } tweet_box.setVisible(true); }); win.setSize(380, 400); win.setVisible(true); You will find these and more examples in directory ''src/examples'' in the efl source code. All you need to run is: node === Twitter edje theme === Theming the tweet in edj allows you to separate presentation details from the code. In a nutshell, you create themes in edje by creating "parts" inside groups, the basic elements of an edje theme. For example, you can create text parts to hold text and rectangles. For traditional widgets, you can create "swallow" parts that the application can use to show buttons, text entry, etc. For more information, check the EDJE tutorial FIXME here. For now, first create an edc - the EDJE source format - file with the following contents: collections { group { name: "tweet"; parts { part { name: "user_icon"; type: SWALLOW; description { rel1 { relative: 0.0 0.0; offset: 2 2; } rel2 { relative: 0.0 0.0; offset: 50 50 ; } } } part { name: "user_name"; type: TEXT; effect: SOFT_SHADOW; description { color: 0 190 255 255; rel1 { relative: 1.0 0.0; to_x: "user_icon"; offset: 7 4; } rel2 { relative: 1.0 0.0; to_x: "user_icon"; offset: 120 30; } text { text: "User Name"; size: 12; font: "sans:style=Bold"; min: 1 1; ellipsis: -1; align: 0.0 0.0; } } } part { name: "screen_name"; type: TEXT; description { rel1 { relative: 1.0 0.0; to: "user_name"; offset: 15 4; } rel2 { relative: 1.0 1.0; to: "user_name"; offset: 75 10; } text { text: "scname"; size: 10; font: "sans"; min: 1 1; ellipsis: -1; align: 0.0 0.0; } } } part { name: "tweet_text"; type: SWALLOW; description { rel1 { relative: 0.0 1.0; to: "user_name"; offset: 0 0; } rel2 { relative: 0.0 1.0; to: "user_name"; offset: 250 80; } } } } } } Then compile it to the .edj format that your app will load: ~$ edje_cc your_edc_file.edc # Will generate your_edc_file.edj