Now we're ready to look at the JavaScript that makes it all work. In this section, we'll code the notes-page.js file.
Initialization
First we import the data/observable and data/observable-array modules. These are built-in modules in NativeScript that allow us to create observable objects and arrays. Observables allow us to automatically update the UI whenever these objects and arrays get updated.
In our app, pageArray is used for storing the array of notes, and pageData is used for tying it to the page. pageData also serves as the general container for all data that we want to show in the UI.
- var Observable = require("data/observable");
- var ObservableArray = require("data/observable-array");
- var pageArray = new ObservableArray.ObservableArray();
- var pageData = new Observable.Observable({
- notes: pageArray
- });
- camera: for working with the device camera.
- view : for referring to specific elements in the page. Think of it as the equivalent of document.getElementById in NativeScript.
- ui/enums: a global dictionary of constant values for anything related to UIs.
- ui/animation: for animating elements.
- application-settings: for persisting local data.
- file-system: for working with the filesystem.
- var cameraModule = require("camera");
- var view = require("ui/core/view");
- var uiEnums = require("ui/enums");
- var animation = require("ui/animation");
- var appSettings = require("application-settings");
- var fs = require("file-system");
- var page;
- var notesArr = [];
- var current_index = -1;
pageLoaded()
FunctionFunctions become available in the context of the page by means of using exports. Earlier in the notes-page.xml file, you saw that the pageLoaded() function is executed when the page is loaded.
- exports.pageLoaded = function(args) {
- ...
- }
- page = args.object;
- pageData.set('showForm', true);
- var new_note_title = appSettings.getString('new_note_title');
- var notes = appSettings.getString('notes');
Note that before we push the items into the observable array, we first check if it's empty. We have to do this because using the camera module executes the loaded event on the page once again after an image is selected. This means that if we're not careful, we'll end up pushing duplicates into the array every time the user uses the camera.
- if(!notes){
- notes = [
- {
- index: 0,
- title: '100 push ups'
- },
- {
- index: 1,
- title: '100 sit ups'
- },
- {
- index: 2,
- title: '100 squats'
- },
- {
- index: 3,
- title: '10km running'
- }
- ];
- }else{
- notes = JSON.parse(notes);
- }
- notesArr = notes;
- if(!pageArray.length){
- for(var x = 0; x < notes.length; x++){
- current_index += 1;
- pageArray.push(notes[x]);
- }
- }
- pageData.set('item_title', new_note_title);
- args.object.bindingContext = pageData;
Next, call the animate function. This accepts an object containing the animation settings. Here we want the form to slide down 160 pixels from its original position over a period of 800 milliseconds.
- view.getViewById(page, 'form').animate({
- translate: { x: 0, y: 160 },
- duration: 800,
- });
The newNote() function is executed when the user taps on the New Item action item on the header. This hides and shows the new item ListView and slides the form up or down depending on the current value of showForm.
If showForm is true, which means it's currently being shown, we change the opacity of the ListView to 1 over the course of 400 milliseconds, and then slide the form up to hide it. Otherwise, we hide the ListView and slide the form down.
- exports.newNote = function() {
- var showForm = pageData.get('showForm');
- var top_position = (showForm) ? -160 : 160;
- var list_visibility = (showForm) ? 1 : 0;
- view.getViewById(page, 'list').animate({
- opacity: list_visibility,
- duration: 400
- });
- view.getViewById(page, 'form').animate({
- translate: { x: 0, y: top_position },
- duration: 800,
- });
- pageData.set('showForm', !showForm);
- }
btnLoaded()
FunctionIn the notes-page.xml file, we have a loaded attribute in the button for deleting a note. This is the function that gets executed when that event happens.
By default, the function assigned to the itemTap attribute in the ListView won't get executed when a button is defined inside a ListView item. This is because NativeScript assumes that the actions to be performed for each list item can be triggered only from those buttons.
The code below is a workaround for that default behavior. This basically removes the focus on the delete button so that you can still execute a function when a user taps on a ListView item. In this case, we don't really need this code since we haven't assigned any functionality to item taps, but it is a good tool to have when working with lists.
- exports.btnLoaded = function (args) {
- var btn = args.object;
- btn.android.setFocusable(false);
- }
openCamera()
FunctionNext is the openCamera() function, which gets executed when the user taps on the Attach Image button. The current state is not maintained when using the camera module, so we need to save the title of the new note into the application settings first.
Afterwards we can launch the default camera app in the device by calling the takePicture() method. This method accepts an object containing the picture settings. Once the user has taken a picture and tapped on the Save button in Android or the use image button on iOS, the promise resolves and the callback function passed to then() gets executed.
The actual image is passed as an argument to the function, and we use this to save the file to the documents path. Once that's done, we save the full file path to the app settings and the current app state so that we can get the value later, before saving the note.
- exports.openCamera = function() {
- appSettings.setString('new_note_title', pageData.get('item_title'));
- cameraModule.takePicture({width: 300, height: 300, keepAspectRatio: true}).then(function(img) {
- var filepath = fs.path.join(fs.knownFolders.documents().path, "img_" + (new Date().getTime() / 1000) + ".jpg");
- img.saveToFile(filepath, uiEnums.ImageFormat.jpeg);
- appSettings.setString('new_note_photo', filepath);
- pageData.set('attachment_img', filepath);
- });
- }
Written by Wernher-Bel Ancheta
If you found this post interesting, follow and support us.
Suggest for you:
No comments:
Post a Comment