//# A Basic List //Displaying a list of items loaded from Facebook. //requires the coordinated use of three classes: `ui.widget.ListView`, //`ui.widget.CellView`, and `GCDataSource`. //Import device to get the screen size. import device; //Import `GCDataSource` to store the items. import GCDataSource; //Import the `List` and `Cell` classes to create a list. import ui.widget.List as List; import ui.widget.Cell as Cell; import ui.widget.ButtonView as ButtonView; import ui.TextView as TextView; import ui.TextPromptView as TextPromptView; import ui.View as View; import util.ajax as ajax; var COLOR1 = "rgb(59,89,152)"; var COLOR2 = "rgb(109,132,180)"; var COLOR3 = "rgb(205,216,234)"; var COLOR4 = "rgb(255,255,255)"; var COLOR5 = "rgb(175,189,212)"; var COLOR6 = "rgb(18,20,54)"; var startSearch = "learning"; var InfoDataSource = Class(GCDataSource, function (supr) { this.init = function (opts) { opts = merge( opts, { key: "id", reverse: true, //Sort by oldest last sorter: function (data) { return data.created_time; } } ); supr(this, "init", [opts]); this._searchFor = startSearch; this.load(); }; this.load = function () { this.clear(); this.emit("Clear"); //Search Facebook ajax.get( { url: "http://graph.facebook.com/search", headers: {"Content-Type": "text/plain"}, //This data will be added as query parameters data: {q: this._searchFor, type: "post"}, //Parse the result as JSON type: "json" }, //call `onData` when the search results are loaded bind(this, "onData") ); }; //Customize the sort function, add indices to the items after sorting this.sort = function () { supr(this, "sort"); var i = this._byIndex.length; while (i) this._byIndex[--i].index = i; }; //Prepend zeros to a string this._leadingZero = function (s, length) { s += ""; while (s.length < length) s = "0" + s; return s; }; //This callback is called when the data is loaded this.onData = function (err, response) { if (!err) { //Iterate over the list and parse the date for (var i = 0; i < response.data.length; i++) { var item = response.data[i]; var date = new Date(item.created_time); item.posted = this._leadingZero(date.getHours(), 2) + ":" + this._leadingZero(date.getMinutes(), 2) + " - " + (date.getMonth() + 1) + "/" + date.getDate() + "/" + date.getFullYear(); } //Add the list to the data source this.add(response.data); //Sort the list this.sort(); //Left the view know that the data is ready this.emit("Loaded"); } else { //Something went wrong, publis the `Error` event so that a message can be displayed this.emit("Error"); } }; //Set the search string and load the data this.setSearchFor = function (searchFor) { this._searchFor = searchFor; this.load(); }; }); //## Class: Application //Create an application, set the default properties. exports = Class(GC.Application, function () { this.getCell = function () { var infoList = this._infoList; return new InfoCell({superview: infoList, infoData: this._infoData}); }; this.initUI = function () { this.style.backgroundColor = COLOR4; //Set up the datasource. this._infoData = new InfoDataSource(); this._infoData.on("Clear", bind(this, "onClear")); this._infoData.on("Loaded", bind(this, "onLoaded")); this._infoData.on("Error", bind(this, "onError")); this._title = new TextView({ superview: this, x: 0, y: 0, width: device.width, height: 50, size: 30, text: "Search Facebook", color: COLOR4, backgroundColor: COLOR1 }); this._loadingLabel = new TextView({ superview: this, x: 0, y: 50, width: device.width, height: device.height - 100, size: 18, text: "Searching for: " + startSearch, color: COLOR6 }); //Create the List, which inherits from `ScrollView`. this._infoList = new List({ superview: this.view, x: 0, y: 50, width: device.width, height: device.height - 100, //Use the dataSource: dataSource: this._infoData, selectable: "multi", maxSelections: 10, scrollX: false, getCell: bind(this, "getCell"), visible: false }); this._searchLabel = new TextView({ superview: this, x: 0, y: device.height - 50, width: device.width / 2, height: 50, size: 20, text: "search for:", horizontalAlign: "right", color: COLOR1, backgroundColor: COLOR5 }); this._searchLabel.onInputSelect = bind(this, "onSelectSeach"); this._search = new TextPromptView({ superview: this, x: device.width / 2, y: device.height - 50, width: device.width / 2, height: 50, size: 20, text: startSearch, horizontalAlign: "left", padding: [0, 0, 0, 6], color: COLOR1, backgroundColor: COLOR5, value: startSearch, prompt: "Enter a search term:" }); this._search.on("Change", bind(this, "onChangeSearch")); }; //This callback is called when the search label is clicked this.onSelectSeach = function () { this._search.showPrompt(); }; //When there's a new text entered in the prompt dialog then this callback is called //and Facebook is searched again this.onChangeSearch = function (value) { this._loadingLabel.setText("Searching for: " + value); this._infoData.setSearchFor(value); }; //Something in the request went wrong this.onError = function () { this._loadingLabel.setText("Failed to load data"); }; //This function is called when a new search starts, the list is hidden and the searching message is shown this.onClear = function () { this._infoList.style.visible = false; this._loadingLabel.style.visible = true; }; //This callback is called when the search data is loaded this.onLoaded = function () { this._infoList.style.visible = true; this._loadingLabel.style.visible = false; }; this.launchUI = function () {}; }); //## Class: InfoCell //Subclass a Cell which is a view, it can have child views, and accepts data from a List. var InfoCell = Class(Cell, function (supr) { this.init = function (opts) { this._infoData = opts.infoData; opts.width = device.width; opts.height = 75; supr(this, "init", [opts]); //The TextView showing who posted the message this._from = new TextView({ superview: this, x: 10, y: 5, width: device.width - 20, height: 20, size: 13, horizontalAlign: "left", color: COLOR2 }); //The time and date when the message was posted this._posted = new TextView({ superview: this, x: 10, y: 5, width: device.width - 20, height: 20, size: 13, horizontalAlign: "right", color: COLOR2 }); //The message this._message = new TextView({ superview: this, x: 10, y: 25, width: device.width - 20, height: 47, size: 13, horizontalAlign: "left", verticalAlign: "top", wrap: true, autoFontSize: false, autoSize: false, clip: true, color: COLOR6 }); }; this._toLength = function (s, length) { if (s.length > length) { var i = Math.max(0, length - 10); while (i < length - 1) { if (s[i] === " ") { break; } i++; } s = s.substr(0, i) + "..."; } return s; }; this.update = function () { var data = this._data; //Set the color depending on if it's an even or odd row this.style.backgroundColor = ((data.index & 1) === 0) ? COLOR3 : COLOR4; //Show the first 40 characters of the name this._from.setText(this._toLength(data.from.name || "", 40)); //Show the time and date this._posted.setText(data.posted); //Show the first 100 characters of the message this._message.setText(this._toLength(data.message || "", 100)); }; //Called when a cell is put on screen. //We'll use it to update our TextView child. this.setData = function (data) { this._data = data; this.update(); }; }); //Run this code in the simulator, and you should see something like the following screenshot. //You can drag the list up and down, but not right or left. //listview screenshot