Step-by-step guide on incorporating an external JavaScript library into an Ionic 3 TypeScript project

As part of a project, I am tasked with creating a custom thermostat app. While I initially wanted to use Ionic for this task, I encountered some difficulty in integrating the provided API into my project. The API.js file contains all the necessary functions to communicate with our server and retrieve data. However, since the server returns XML data, my attempts to create compatible functions using a provider have been unsuccessful so far. Now, I am trying to include the given API.js file directly into my project, but I'm encountering challenges in doing so as well. Therefore, I would greatly appreciate any guidance on either incorporating this external API into my ionic project effectively or working with the returned XML data (such as displaying it in the app and sending modified data back).

Given the size of both files, I have included snippets below and complete files can be found via pastebin links.

The available commands we can utilize are day, time, currentTemperature, targetTemperature, dayTemperature, nightTemperature, weekProgramState, and weekProgram.

Thank you in advance!

The API.js

var ServerUrl = '';

Type = {
    Day : 'day',
    Night : 'night'
};

Days = {
    Monday : 'Monday',
    Tuesday : 'Tuesday',
    Wednesday : 'Wednesday',
    Thursday : 'Thursday',
    Friday : 'Friday',
    Saturday : 'Saturday',
    Sunday : 'Sunday'
};

var MinTemperature = parseFloat(5.0);
var MaxTemperature = parseFloat(30.0);
var MaxSwitches = 5;

var Time;
var CurrentDay;
var DayTemperature;
var NightTemperature;
var CurrentTemperature;
var TargetTemperature;
var ProgramState;

var Program = {};
Program[Days.Monday]    = [];
Program[Days.Tuesday]   = [];
Program[Days.Wednesday] = [];
Program[Days.Thursday]  = [];
Program[Days.Friday]    = [];
Program[Days.Saturday]  = [];
Program[Days.Sunday]    = [];

/* Retrieve the program for a specific day
*/
function getProgram(day) {
    return Program[day];
}

/* Sorts and merges heating periods (when the heating is on), eliminating overlaps
*/
function sortMergeProgram(day) {
    var program = getProgram(day);
    program.sort(function(a, b){return parseTime(a[0])-parseTime(b[0])});
    for (var i = 0; i < program.length - 1; i++) {
        if (parseTime(program[i][1]) >= parseTime(program[i+1][0])) {
            var start = (program[i][0]);
            var end = (parseTime(program[i][1]) > parseTime(program[i+1][1])) ? program[i][1] : program[i+1][1];
            program.splice(i, 2);
            program.push([start, end]);
            sortMergeProgram(day);
            break;
        }
    }
}

/* Retrieves all data from the server except for weekProgram
*/
function get(attribute_name, xml_tag) {
    return requestData(
        "/"+attribute_name,
        function(data) {
            return $(data).find(xml_tag).text();
        }
    );
}

/* Retrieves the week program
*/
function getWeekProgram() {
    return requestData(
        '/weekProgram',
        function(data) {
            $(data).find('day').each(function() {
                var day = $(this).attr('name');
                Program[day] = [];
                $(this).find('switch').each(function() {
                    if ($(this).attr('state') == 'on') {
                        if ($(this).attr('type') == Type.Day) {
                            getProgram(day).push([$(this).text(), '00:00']);
                        } else {
                            getProgram(day)[getProgram(day).length - 1][1] = $(this).text();
                        }
                    }
                })
            });
            return Program;
        }
    );
}

The returned XML data

<thermostat><current_day>Thursday</current_day>
<time>23:32</time>
<current_temperature>16.0</current_temperature>
<target_temperature>16.0</target_temperature>
<day_temperature>22.0</day_temperature>
<night_temperature>19.0</night_temperature>
<week_program_state>off</week_program_state>
<week_program state="off">
  <day name="Monday">
    <switch type="day" state="off">00:00</switch>
    <switch type="day" state="off">00:00</switch>
    <switch type="day" state="off">00:00</switch>
    <switch type="night" state="off">00:00</switch>
    <switch type="night" state="off">00:00</switch>
    <switch type="night" state="off">00:00</switch>
    <switch type="day" state="on">05:00</switch>
    <switch type="night" state="on">08:00</switch>
    <switch type="day" state="on">12:00</switch>
    <switch type="night" state="on">14:00</switch>
  </day>
  <day name="Tuesday">
    <switch type="day" state="off">00:00</switch>
    <switch type="day" state="off">00:00</switch>
    <switch type="day" state="off">00:00</switch>
    <switch type="day" state="off">00:00</switch>
    <switch type="day" state="off">00:00</switch>
    <switch type="night" state="off">00:00</switch>
    <switch type="night" state="off">00:00</switch>
    <switch type="night" state="off">00:00</switch>
    <switch type="night" state="off">00:00</switch>
    <switch type="night" state="off">00:00</switch>
  </day>

Answer №1

What I can suggest is creating a file called API.ts. Inside, you should create an API class with properties and functions similar to API.js, but taking into account the syntax of Typescript.

It seems that the original author intended to use jquery in the file, but it was not imported. So, I would recommend importing it as well. Assuming you have been provided with this file, make sure you place it inside src/assets and modify the import path in my code to match the filename accordingly.

This is what I have for you:

import * as $ from '.assets/jquery.js';

export class API {
  ServerUrl = '';

  Type = {
    Day: 'day',
    Night: 'night'
  };

  Days = {
    Monday: 'Monday',
    Tuesday: 'Tuesday',
    Wednesday: 'Wednesday',
    Thursday: 'Thursday',
    Friday: 'Friday',
    Saturday: 'Saturday',
    Sunday: 'Sunday'
  };

  MinTemperature = parseFloat('5.0');
  MaxTemperature = parseFloat('30.0');
  MaxSwitches = 5;

  Time;
  CurrentDay;
  DayTemperature;
  NightTemperature;
  CurrentTemperature;
  TargetTemperature;
  ProgramState;

  Program:any = {};

  constructor() {
    this.Program[this.Days.Monday]    = [];
    this.Program[this.Days.Tuesday]   = [];
    this.Program[this.Days.Wednesday] = [];
    this.Program[this.Days.Thursday]  = [];
    this.Program[this.Days.Friday]    = [];
    this.Program[this.Days.Saturday]  = [];
    this.Program[this.Days.Sunday]    = [];
  }

  /* Retrieve day program */
  getProgram(day) {
    return this.Program[day];
  }

  /* Sort the heating periods (the periods when the heating is on) and merge overlapping ones */
  sortMergeProgram(day) {
    let program = this.getProgram(day);
    program.sort(function(a, b) {
      return this.parseTime(a[0]) - this.parseTime(b[0])
    });
    for (let i = 0; i < program.length - 1; i++) {
      if (this.parseTime(program[i][1]) >= this.parseTime(program[i + 1][0])) {
        let start = (program[i][0]);
        let end = (this.parseTime(program[i][1]) > this.parseTime(program[i + 1][1])) ? program[i][1] : program[i + 1][1];
        program.splice(i, 2);
        program.push([start, end]);
        this.sortMergeProgram(day);
        break;
      }
    }
  }

  /* Retrieve all data from the server except for weekProgram */
  get(attribute_name, xml_tag) {
    return this.requestData(
      "/" + attribute_name,
      function(data) {
        return $(data).find(xml_tag).text();
      }
    );
  }

  /* Retrieve the week program */
  getWeekProgram() {
    return this.requestData(
    '/weekProgram',
    function(data) {
      $(data).find('day').each(function() {
        let day = (<any>$(this)).attr('name');
        this.Program[day] = [];
        $(this).find('switch').each(function() {
          if ((<any>$(this)).attr('state') == 'on') {
            if ((<any>$(this)).attr('type') == this.Type.Day) {
              this.getProgram(day).push([$(this).text(), '00:00']);
            } else {
              this.getProgram(day)[this.getProgram(day).length - 1][1] = $(this).text();
            }
          }
        })
      });
      return this.Program;
    }
  );
}

  /* Upload all data to the server except for currentTemperature and weekProgram */
  put(attribute_name, xml_tag, value) {
    this.uploadData("/" + attribute_name, "<" + xml_tag + ">" + value + "</" + xml_tag + ">");
  }

  requestData(address, func) {
    let result;
    (<any>$).ajax({
      type: "get",
      url: this.ServerUrl + address,
      dataType: "xml",
      async: false,
      success: function(data) {
        result = func(data);
      }
    });
    return result;
  }

  setWeekProgram() {
    let doc = document.implementation.createDocument(null, null, null);
    let program = doc.createElement('week_program');
    program.setAttribute('state', this.ProgramState ? 'on' : 'off');
    for (let key in this.Program) {
      let day = doc.createElement('day');
      day.setAttribute('name', key);

      let daySwitches = [];
      let nightSwitches = [];

      let i, text, sw;
      let periods = this.getProgram(key);
      for (i = 0; i < periods.length; i++) {
        daySwitches.push(periods[i][0]);
        nightSwitches.push(periods[i][1]);
      }

      for (i = 0; i < this.MaxSwitches; i++) {
        sw = doc.createElement('switch');
        sw.setAttribute('type', this.Type.Day);

        if (i < daySwitches.length) {
          sw.setAttribute('state', 'on');
          text = doc.createTextNode(daySwitches[i]);
        } else {
          sw.setAttribute('state', 'off');
          text = doc.createTextNode('00:00');
        }
        sw.appendChild(text);
        day.appendChild(sw);
      }

      for (i = 0; i < this.MaxSwitches; i++) {
        sw = doc.createElement('switch');
        sw.setAttribute('type', this.Type.Night);

        if (i < nightSwitches.length) {
          sw.setAttribute('state', 'on');
          text = doc.createTextNode(nightSwitches[i]);
        } else {
          sw.setAttribute('state', 'off');
          text = doc.createTextNode('00:00');
        }
        sw.appendChild(text);
        day.appendChild(sw);
      }
    program.appendChild(day);
  }
doc.appendChild(program);
this.uploadData('/weekProgram', (new XMLSerializer()).serializeToString(doc));
}

setDefault() {
let doc = document.implementation.createDocument(null, null, null);
let program = doc.createElement('week_program');
program.setAttribute('state', this.ProgramState ? 'on' : 'off');
for (let key in this.Program) {
  let day = doc.createElement('day');
  day.setAttribute('name', key);

  let daySwitches = [];
  let nightSwitches = [];

  let i, text, sw;

  for (i = 0; i < this.MaxSwitches; i++) {
    sw = doc.createElement('switch');
    sw.setAttribute('type', this.Type.Night);
    sw.setAttribute('state', 'off');
    text = doc.createTextNode('00:00');
    sw.appendChild(text);
    day.appendChild(sw);
  }

  for (i = 0; i < this.MaxSwitches; i++) {
    sw = doc.createElement('switch');
    sw.setAttribute('type', this.Type.Day);
    sw.setAttribute('state', 'off');
    text = doc.createTextNode('00:00');
    sw.appendChild(text);
    day.appendChild(sw);
  }

  program.appendChild(day);
}
doc.appendChild(program);
this.uploadData('/weekProgram', (new XMLSerializer()).serializeToString(doc));
}

uploadData(address, xml) {
(<any>$).ajax({
  type: "put",
  url: this.ServerUrl + address,
  contentType: 'application/xml',
  data: xml,
  async: false
});
}

parseTime(t) {
return parseFloat(t.substr(0, 2)) + parseFloat(t.substr(3, 2)) / 60;
}

/* Add a heating period for a specific day */
addPeriod(day, start, end) {
let program = this.getWeekProgram()[day];
program.push([start, end]);
this.sortMergeProgram(day);
this.setWeekProgram();
}

/* Remove a heating period from a specific day.
 idx is the idex of the period with values from 0 to 4
*/
removePeriod(day, idx) {
let program = this.getWeekProgram()[day];
let start = program[idx][0];
let end = program[idx][1];
program.splice(idx, 1);
this.setWeekProgram();
}

/* Check whether the temperature is within the range [5.0,30.0] */
inTemperatureBoundaries(temp) {
temp = parseFloat(temp);
return (temp >= this.MinTemperature && temp <= this.MaxTemperature);
}
}

Now, you can import the API in any Ionic component:

import { API } from './API'

And then use it in your code as follows:

export class yourPage {
constructor(public api: API){}

yourFunction() {
this.api.setDefault();
}
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Explore how Next.js's getServerSideProps feature incorporates loading animations and improves

I have implemented getServerSideProps in my project's pages/post/index.js file: import React from "react"; import Layout from "../../components/Layout"; function Post({ post }) { console.log("in render", post); return ( <Layout title={pos ...

Unable to retrieve the image

When trying to fetch an image, I encountered the following error: Failed to load resource: the server responded with a status of 404 (Not Found) TopBar.jsx import { useContext } from "react"; import { Link } from "react-router-dom"; ...

What is the most efficient way to align a localStorage variable with its corresponding page?

In my current project, I have developed a component that is utilized in an online science lab setting. To ensure continuity for researchers who navigate away from the page and return later, I have integrated the use of localStorage. The goal is to preserv ...

What's New with Material 3 in Angular 17?

Even though I've taken the time to read all of the documentation at https://github.com/material-components/material-web/blob/main/docs/quick-start.md, I'm still struggling to figure out how to incorporate this into my Angular 17 project. I went ...

Building and executing an Angular 2 program on the Windows platform: Step-by-step guide

After successfully installing npm and related packages including TypeScript and Angular 2, I am encountering difficulties running Angular 2 in my browser on a Windows platform. Can someone provide a step-by-step guide to help me create and run Angular 2 ...

An effective way to connect the ng-model of a <select> element with ng-options within an ng-repeat loop

My task list consists of: [{ Title: "Title1", Position: "9" },{ Title: "Title2", Position: "1" },{ Title: "Title3", Position: "5" },{ Title: "Title4", Position: "7" }] I am attempting to generate a series of <select> ...

Error 404 in Angular HTTP Request

I'm encountering a 404 error while attempting to send a post request, along with a 'possibly unhandled rejection' error. Given my limited experience with Angular, any advice would be greatly appreciated. I've gone through the documentat ...

The type 'string | undefined' cannot be assigned to type 'string'

I am facing a challenge in comparing two arrays, where one array is sourced from a third-party AWS service and its existence cannot be guaranteed. Despite my efforts to handle potential errors by incorporating return statements in my function calls, I con ...

Encountering Issues with Discord JS as Member Fetch Returns Undefined

I'm facing an issue with fetching specific server members by their user id in order to assign a role to them. I keep getting an undefined response each time. Even though this bot has administrator permission and all required intents are assigned, I a ...

What is the process for incorporating ejs into the source attribute of an image element?

Code Snippet: <img class="card-img-top" alt="..."><%= articles.image %><img> Server Setup: const express = require('express') const app = express() const router = require('./routes/article') app ...

Restrict the properties of an object to match the properties of a different object

I am currently developing an Object patching utility function with the following code snippet class Test{ a:number; b:number; } var c:Test={a:0,b:1} function patchable<T>(obj:T){ return { patch:function<K>(prop:K){ return patc ...

Is there a constraint on JSON data?

Is there a limit to the amount of data that JSON with AJAX can handle in outgoing and returning parameters? I am trying to send and receive a file with 10,000 lines as a string from the server. How can I accomplish this task? Can a single parameter manage ...

What is the best way to incorporate a condition within react material-ui components?

Currently I am constructing a generic data table using react and material-ui. My programming background is in c# and java, as well as some early experience with javascript. However, I am encountering syntax issues within reactjs. Here is the particular pi ...

What could be causing the issue when the selected option is being changed and the condition does not work

Whenever the selection in a select element is changed, the corresponding text should also change. Check out this Fiddle here. (function($) { 'use strict'; function updateResultText() { var s1_is_1 = $("#s1").value === '1', ...

React components are failing to display data as expected

I need to display certain data based on the id provided in the url. When I use console.log() with res.json, I can see the data but I'm unsure how to pass it to the 'articleComponent'. const Articles = () => { const query = (id) => ...

What is the optimal method for generating numerous records across various tables using a single API request in a sequelize-node.js-postgres environment?

I need to efficiently store data across multiple separate tables in Postgres within a single API call. While I can make individual calls for each table, I am seeking advice on the best way to handle this. Any tips or suggestions would be greatly appreciate ...

Navigating through a React application with several workspaces - the ultimate guide

Currently, I am working on implementing a monorepo setup inspired by this reference: https://github.com/GeekyAnts/nativebase-templates/tree/master/solito-universal-app-template-nativebase-typescript In this repository, there are 4 distinct locations wher ...

Perform Action Only When Clicking "X" Button on JQuery Dialog

I have a dialog box with two buttons, "Yes" and "No", which trigger different functions when clicked. $('#divDialog').dialog({ modal:true, width:450, resizable: false, buttons: [{ text: 'Yes', ...

Attention: React is unable to identify the `pId` property on a DOM element

After removing the span tag below, I noticed that there were no warnings displayed. <span onClick={onCommentClick} className={'comment'}> <AiOutlineComment className={"i"} size={"20px"}/> Co ...

What is causing the addListener function in the events class to malfunction?

I am a beginner in the world of node.js and attempting to execute this piece of code: var eventlib= require('events'); var emitter= new eventlib(); eventlib.addListener('MessageEvent', function() { console.log('Registered the ...