Can’t Attach PDF File to Email in JavaScript Using smtpjs

  1. Summarize the problem

I am unable to attach a PDF file to an email to be sent to an email address. The PDF file is in the same folder as the HTML file, which contains the JavaScript code to send the email using SMTPJS.

Expected result:
An email is sent to the designated email address with the pdf file without any problems.

Actual result:
No email was sent at all.

  1. Describe what you’ve tried

#1: Attempt by putting file name and extension in quotes like this:

PFD_Articles.pdf -> ‘PFD_Articles.pdf’

Again, the actual result is produced, not the expected one.

  1. Show some code
Email.send
(
    {
        Host: "smtp.gmail.com",
        Username: "[email protected]",
        Password: "password",
        To: '[email protected]',
        From: "[email protected]",
        Subject: "<h1> ddd </h1>",
        Body: "And this is the body",
        Attachments:
            [
                {
                    name: 'PFD_Articles.pdf'
                }
            ]
    }).then
(
    alert("Successful! Please check your email inbox. Otherwise, you may have to enter your email address again.")
);

FormData to string rendering

I need to be able to generate multipart-form data and to convert that to string to store it locally. For example, if I generate the form data as follows:

  var form = new FormData();
  form.append('part1', 'part 1 data');
  form.append('part2', 'part 2 data');

I want to ask it to returns its rendering as a string (how it would get transmitted over web):

----------------------------900078007145468816304698
Content-Disposition: form-data; name="part1"

part 1 data
----------------------------900078007145468816304698
Content-Disposition: form-data; name="part2"

part 2 data
----------------------------900078007145468816304698--

Javascript is not exactly my strength, so hoping someone has a simple idea on how to do this.

Translating javascript into R: secondary sentinel products

I’m doing pretty good in R but can’t figure out how to translate this javascript (at least I think it’s javascript…might be python?) into R:

      /*
Author of the script: Carlos Bentes
*/

// Normalized Difference Vegetation Index
var ndvi = (B08-B04)/(B08+B04);

// Threshold for vegetation
var veg_th = 0.4;

// Simple RGB
var R = 2.5*B04;
var G = 2.5*B03;
var B = 2.5*B02;

// Transform to Black and White
var Y = 0.2*R + 0.7*G + 0.1*B;
var pixel = [Y, Y, Y];

// Change vegetation color
if(ndvi >= veg_th)
  pixel = [0.1*Y, 1.8*Y, 0.1*Y];

return pixel;

This is the Green City Index which is part of the repository of custom scripts that can be used with Sentinel-Hub services.

Specifically I’m having issues with

var pixel = [Y, Y, Y];

And

if(ndvi >= veg_th)
  pixel = [0.1*Y, 1.8*Y, 0.1*Y];

return pixel;

I think var pixel = [Y, Y, Y]; is the same as pixel <- c(Y, Y, Y)? Which means in the if statement I’d have

if(ndvi >= veg_th){ 
   pixel <- c(0.1*Y, 1.8*Y, 0.1*Y) 
   return(pixel)
}

But I’m not getting results: Error in if (ndvi >= veg_th) { : argument is not interpretable as logical

Thanks for taking a look!

Canvas will not build unless screen is refreshed? Is there any way to build canvas without window load?

I have this moving flame element that uses the canvas to display using JavaScript. Well when I refresh the page it works just fine, but the problem is the canvas is part of a template in a lesson that uses classic JS/Node/DOM and reads content from JSON data. So the lesson switches pages without refresh causing the canvas to not be created. So is there anyway to fix this?

So inside my function that reads the JSON data I have these lines

canvasFlame(); <---- this calls the function to build the canvas

let containFinal = document.getElementById('flame-container');
let canvasDem = document.getElementById('sketch-0');<------- the canvas container
containFinal.appendChild(canvasDem);<----- it's dropped into the "flame-container"

Here is the canvasFlame function (called in from a seperate file)
function canvasFlame(){

var particles = [];
let containFinal = document.getElementById('flame-container');
containFinal.width = 400;
containFinal.height = 400;

var Particle = function(x, y) {

    this.x = x + random(-10, 10);
    this.y = y + random(-10, 10);
    this.vx = random(-2.5, 2.5);
    this.vy = random(-5, 5);
    this.radius = (random() > 0.75) ? random(25, 50) : 1 + random(1, 20);
    this.lifespan = random(25, 50);
    this.charge = this.lifespan;
    this.color = {
        r: round(random(255)),
        g: round(random(75)),
        b: round(random(50))
    };
}

Particle.prototype = {

    update: function() {
        this.charge--;
        this.radius--;
        this.x += this.vx;
        this.y += this.vy;
    },

    draw: function(ctx) {

        var gradient = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.radius);
        gradient.addColorStop(0, 'rgba(' + this.color.r + ', ' + this.color.g + ', ' + this.color.b + ', ' + this.opacity + ')');
        gradient.addColorStop(0.5, "rgba(" + this.color.r + ", " + this.color.g + ", " + this.color.b + ", " + this.opacity + ")");
        gradient.addColorStop(1, "rgba(" + this.color.r + ", " + this.color.g + ", " + this.color.b + ", 0)");

        ctx.fillStyle = gradient;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, TWO_PI, false);
        ctx.fill();
    }
};

Sketch.create({
    center: {},
    setup: function() {
        
        this.resize();

        for (var i = 0; i < 100; i++) {
            particles.push(new Particle(this.center.x, this.center.y));
        }
    },

    resize: function() {
        this.center.x = containFinal.width * 0.5;
        this.center.y = containFinal.height * 0.5;
    },

    draw: function() {

        this.globalCompositeOperation = "source-over";
        this.fillStyle = '#000000';
        this.fillRect(0, 0, containFinal.width, containFinal.height);
        this.globalCompositeOperation = "lighter";

        var p, ip = particles.length;
        
        while (ip--) {
            p = particles[ip];
            p.opacity = round(p.charge / p.lifespan * 100) / 100;
            p.draw(this);
            p.update();
            if (p.charge < 0 || p.radius < 0) {
                particles[ip] = new Particle(containFinal.x || this.center.x, containFinal.y || this.center.y);
            }
        }
    }
});

}

That file then calls the Sketch.create function in a seperate js file.
Here that code. [see below]

var Sketch=function(){function e(e){e=n(e||{},l);var t=”sketch-“+r++,o=e.hasOwnProperty(“canvas”),u=o?e.canvas:document.createElement(“canvas”);

switch(e.type){case m:try{s=u.getContext(“webgl”,e)}catch(d){}try{s=s||u.getContext(“experimental-webgl”,e)}catch(d){}if(!s)throw”WebGL not supported”;break;case c:try{s=u.getContext(“2d”,e)}catch(d){}if(!s)throw”Canvas not supported”;break;default:u=s=document.createElement(“div”)}return s.canvas=u,u.className=”sketch”,o?e.autoresize=!1:(e.container.appendChild(u),e.hasOwnProperty(“autoresize”)||(e.autoresize=l.autoresize),u.id=t),n(self,g),n(s,e),n(s,p),a(),e.autoresize&&i(),w.push(s),s.autostart&&setTimeout(s.start,0),s}function n(e,n){for(var t in n)e.hasOwnProperty(t)||(e[t]=n[t]);return e}function t(e){function n(e,n){return function(){e.call(n,arguments)}}var t={};for(var o in e)t[o]=”function”==typeof e[o]?n(e[o],e):e[o];return t}function o(e,n){e.length=0;for(var t=0,o=n.length;o>t;t++)e[t]=n[t];return e}function a(){function e(e){return M[e]||String.fromCharCode(e)}function n(e){s.mouse.ox=s.mouse.x,s.mouse.oy=s.mouse.y,s.mouse.x=e.x,s.mouse.y=e.y,s.mouse.dx=s.mouse.x-s.mouse.ox,s.mouse.dy=s.mouse.y-s.mouse.oy}function a(e){var n,o=t(e);o.original=e;for(var a=s.canvas,u=0,i=0;a;a=a.offsetParent)u+=a.offsetLeft,i+=a.offsetTop;if(o.touches&&o.touches.length)for(var r,c=o.touches.length-1;c>=0;c–)r=o.touches[c],r.x=r.pageX-u,r.y=r.pageY-i,n=A[c]||r,r.dx=r.x-n.x,r.dy=r.y-n.x,r.ox=n.x,r.oy=n.y,A[c]=t(r);else o.x=o.pageX-u,o.y=o.pageY-i,n=A.mouse||o,o.dx=o.x-n.x,o.dy=o.y-n.y,o.ox=n.x,o.oy=n.y,A.mouse=o;return o}

function u(e){
e.preventDefault(),e=a(e),o(s.touches,e.touches),n(s.touches[0]),s.touchstart&&s.touchstart(e),s.mousedown&&s.mousedown(e)
}
function r(e){
e=a(e),o(s.touches,e.touches),n(s.touches[0]),s.touchmove&&s.touchmove(e),s.mousemove&&s.mousemove(e)
}
function c(e){
if(e=a(e),e.touches.length)for(var n in A)e.touches[n]||delete A[n];else A={};s.touchend&&s.touchend(e),s.mouseup&&s.mouseup(e)
}
function m(e){
e=a(e),s.mouseover&&s.mouseover(e)
}
function d(e){
e=a(e),s.dragging||(x(s.canvas,”mousemove”,h),x(s.canvas,”mouseup”,v),y(document,”mousemove”,h),y(document,”mouseup”,v),s.dragging=!0),o(s.touches,[e]),s.touchstart&&s.touchstart(e),s.mousedown&&s.mousedown(e)
}
function h(e){
e=a(e),n(e),o(s.touches,[e]),s.touchmove&&s.touchmove(e),s.mousemove&&s.mousemove(e)
}
function f(e){
e=a(e),s.mouseout&&s.mouseout(e)
}
function v(e){
e=a(e),s.dragging&&(x(document,”mousemove”,h),x(document,”mouseup”,v),y(s.canvas,”mousemove”,h),y(s.canvas,”mouseup”,v),s.dragging=!1),delete A.mouse,s.touchend&&s.touchend(e),s.mouseup&&s.mouseup(e)
}
function w(e){
e=a(e),s.click&&s.click(e)
}
function l(n){s.keys[e(n.keyCode)]=!0,s.keys[n.keyCode]=!0,s.keydown&&s.keydown(n)}function g(n){s.keys[e(n.keyCode)]=!1,s.keys[n.keyCode]=!1,s.keyup&&s.keyup(n)}var M={8:”BACKSPACE”,9:”TAB”,13:”ENTER”,16:”SHIFT”,27:”ESCAPE”,32:”SPACE”,37:”LEFT”,38:”UP”,39:”RIGHT”,40:”DOWN”};for(var k in M)p.keys[M[k]]=!1;var A={};y(s.canvas,”touchstart”,u),y(s.canvas,”touchmove”,r),y(s.canvas,”touchend”,c),y(s.canvas,”mouseover”,m),y(s.canvas,”mousedown”,d),y(s.canvas,”mousemove”,h),y(s.canvas,”mouseout”,f),y(s.canvas,”mouseup”,v),y(s.canvas,”click”,w),y(document,”keydown”,l),y(document,”keyup”,g),y(window,”resize”,i)}function u(){if(!h){var e=Date.now();s.dt=e-s.now,s.millis+=s.dt,s.now=e,s.update&&s.update(s.dt),s.autoclear&&s.clear(),s.draw&&s.draw(s)}h=++h%s.interval,f=requestAnimationFrame(u)}function i(){if(s.autoresize){
var e=s.type===d?s.style:s.canvas;
s.fullscreen?(s.height=e.height=400,s.width=e.width=400):(e.height=s.height,e.width=s.width),s.resize&&s.resize()}}
var s,r=0,c=”canvas”,m=”web-gl”,d=”dom”,h=0,f=-1,v={},w=[],l={fullscreen:!0,autostart:!0,autoclear:!0,autopause:!0,autoresize:!0,container:document.body,interval:1,type:c},g={PI:Math.PI,TWO_PI:2*Math.PI,HALF_PI:Math.PI/2,QUARTER_PI:Math.PI/4,abs:Math.abs,acos:Math.acos,asin:Math.asin,atan2:Math.atan2,atan:Math.atan,ceil:Math.ceil,cos:Math.cos,exp:Math.exp,floor:Math.floor,log:Math.log,max:Math.max,min:Math.min,pow:Math.pow,round:Math.round,sin:Math.sin,sqrt:Math.sqrt,tan:Math.tan,random:function(e,n){return e&&”number”==typeof e.length&&e.length?e[Math.floor(Math.random()e.length)]:(“number”!=typeof n&&(n=e||1,e=0),e+Math.random()(n-e))}},p={millis:0,now:0/0,dt:0/0,keys:{},mouse:{x:0,y:0,ox:0,oy:0,dx:0,dy:0},touches:[],initialized:!1,dragging:!1,running:!1,start:function(){s.running||(s.setup&&!s.initialized&&(s.autopause&&(y(window,”focus”,s.start),y(window,”blur”,s.stop)),s.setup()),s.initialized=!0,s.running=!0,s.now=Date.now(),u())},stop:function(){cancelAnimationFrame(f),s.running=!1},toggle:function(){(s.running?s.stop:s.start)()},clear:function(){s.canvas&&(s.canvas.width=s.canvas.width)},destroy:function(){var e,n,t,o,a,u;w.splice(w.indexOf(s),1),s.stop();for(n in v){for(t=v[n],a=0,u=t.length;u>a;a++)e=t[a],x(e.el,n,e.fn);delete v[n]}s.container.removeChild(s.canvas);for(o in s)s.hasOwnProperty(o)&&delete s[o]}},y=function(){function e(e,n,t){v[n]||(v[n]=[]),v[n].push({el:e,fn:t})}
return window.addEventListener?function(n,t,o){
n.addEventListener(t,o,!1),e(n,t,o)
}:
window.attachEvent?function(n,t,o){n.attachEvent(“on”+t,o),e(n,t,o)}:function(n,t,o){n[“on”+t]=o,e(n,t,o)}}(),x=function(){function e(e,n,t){if(v[n])for(var o,a=v[n].length-1;a>=0;a–)o=v[n][a],o.el===e&&o.fn===t&&v[n].splice(a,1)}
return window.removeEventListener?function(n,t,o){n.removeEventListener(t,o,!1),e(n,t,o)}:window.detachEvent?function(n,t,o){n.detachEvent(“on”+t,o),e(n,t,o)}:(el[“on”+ev]=null,e(el,ev,fn),void 0)}();return{CANVAS:c,WEB_GL:m,DOM:d,instances:w,create:e}}();Date.now||(Date.now=function(){return+new Date}),function(){for(var e=0,n=[“ms”,”moz”,”webkit”,”o”],t=0;n.length>t&&!window.requestAnimationFrame;++t)window.requestAnimationFrame=window[n[t]+”RequestAnimationFrame”],window.cancelAnimationFrame=window[n[t]+”CancelAnimationFrame”]||window[n[t]+”CancelRequestAnimationFrame”];window.requestAnimationFrame||(window.requestAnimationFrame=function(n){var t=Date.now(),o=Math.max(0,16-(t-e)),a=window.setTimeout(function(){n(t+o)},o);return e=t+o,a}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(e){clearTimeout(e)})}();

This link can also be used to for reference bc it’s where the flames came from.
https://codepen.io/nikrowell/pen/doRBdZ

Thanks, I appreciate all the help.

How can I use PC to call someone on the phone [closed]

I want to make a web app, which basically has some saved phone numbers and when I click it, the web app uses my phone’s sim to call that number and we can have a conversation through my PC, I am looking for an API, which basically lets me use my PC to make calls to people and talk through my PC mic, but I’ll be using my phone for the sim, is this possible? what API do I use?

leaflet show or hide layers wfs cql_filter

i use the library Leaflet-WFST.
So I have both wms and wfs layers. With wms, everything is simple there is cql_filter.
I am writing a code where cql_filter is applied when clicking on the checkbox, here is the code:

$('#s23').click(function(){
if($("#s23").is(":checked")){
    if(layer.wmsParams.cql_filter != '' && layer.wmsParams.cql_filter.includes('layer_id=23') == false){
     layer.setParams({ cql_filter: layer.wmsParams.cql_filter + ' OR layer_id=23' });
     }else
     layer.setParams({ cql_filter: 'layer_id=23' });
     layer.setOpacity(1);
}else if(layer.wmsParams.cql_filter.includes(' OR layer_id=23') == true){ l_edit = layer.wmsParams.cql_filter.replace(" OR layer_id=23", "");
layer.setParams({ cql_filter: l_edit });
}else if(layer.wmsParams.cql_filter.includes('layer_id=23 OR ') == true){ l_edit = layer.wmsParams.cql_filter.replace("layer_id=23 OR ", "");
layer.setParams({ cql_filter: l_edit });
}else  layer.setParams({ cql_filter: '' });
     console.log(layer.wmsParams.cql_filter);
});
$('#s29').click(function(){
if($("#s29").is(":checked")){
   console.log(layer);
    if(layer.wmsParams.cql_filter != '' && layer.wmsParams.cql_filter.includes('layer_id=29') == false)
     layer.setParams({ cql_filter: layer.wmsParams.cql_filter + ' OR layer_id=29' });
     else
     layer.setParams({ cql_filter: 'layer_id=29' });
     layer.setOpacity(1);
     console.log(layer.wmsParams.cql_filter);
}else if(layer.wmsParams.cql_filter.includes(' OR layer_id=29') == true){ l_edit = layer.wmsParams.cql_filter.replace(" OR layer_id=29", "");
layer.setParams({ cql_filter: l_edit });
}else if(layer.wmsParams.cql_filter.includes('layer_id=29 OR ') == true){ l_edit = layer.wmsParams.cql_filter.replace("layer_id=29 OR ", "");
layer.setParams({ cql_filter: l_edit });
}else  layer.setParams({ cql_filter: '' });
     console.log(layer.wmsParams.cql_filter);
});

Here, if cql_filter is added when the checkbox is clicked, if it is empty, then cql_filter: ‘layer_id=23’ is triggered, and if there is something in cql_filter, then cql_filter: layer.wmsParams.cql_filter + ‘ OR layer_id=23’
also if the checkbox was cleared, then this layer_id is removed from cql_filter.

I can use this code:

var layer_23 = new L.Filter.EQ('layer_id', 23);
 //var OR = new L.Filter.Or(layer.options.filter, layer_23);
 layer.options.filter = layer_23;
layer.loadFeatures(layer_23);

To add a new filter, but I don’t know how I can remove or edit it.

The question is, how can the same thing be done?

Uncaught TypeError: jQuery(…).autoComplete is not a function error

I have two pages that autocomplete a brand name field and both are almost identical in respect to this function. However one works, autocompleting entries as expected. And the other doesn’t autocorrect. It gets an error as follows:

codebase.core.min.js:6 Uncaught TypeError: jQuery(...).autoComplete is not a function
    at Function.initAutoComplete (brand_list.js:23:34)
    at Function.init (brand_list.js:45:14)
    at HTMLDocument.<anonymous> (brand_list.js:50:26)
    at e (codebase.core.min.js:6:29178)
    at t (codebase.core.min.js:6:29480)

I find it hard to understand how there could be an error with brand_list.js when the same function is called by another program and works perfectly.

Both use the same get_js statement:

    <?php $cb->get_js('_es6/pages/brand_list.js'); ?>

brand_list.js is as follows:

class BrandList {

static initAutoComplete() {
        var brands = [];
            jQuery.ajax({
                url: "./ajax/ajaxFetchBrands.php",
                type: 'post',
                dataType: "json",           
                success: function( data ) {
                    for (var i = 0; i < data.length; i++) {
                    brands.push(data[i].brand_name);
                }
            }
        });
       
        // Init autocomplete functionality
        jQuery('.js-autocompletebrand').autoComplete({

            minChars: 1,
            source: function(term, suggest){
                term = term.toLowerCase();

                let brandsList  = brands;
                let suggestions    = [];
                alert(brandsList.length);
                for (var i = 0; i < brandsList.length; i++) {
                    if (~ brandsList[i].toLowerCase().indexOf(term)) suggestions.push(brandsList[i]);
                }

                suggest(suggestions);
            }
        });
        }

        /*
         * Init functionality
         *
         */
        static init() {
            this.initAutoComplete();
        }
    }

    // Initialize when page loads
    jQuery(() => { BrandList.init(); });

I’ve debuged the ajax script and it is correctly picking up the data to pass back.

The script is as follows:

<?php
ob_start();
session_start();
require '../inc/_global/db_con.php';

//$debugnote = "================================ AJAX FETCH BRANDS ====================================================";
//$query = mysqli_query($con, "insert into debug (note, created_at) values ('$debugnote', NOW())") or die(mysqli_error($con));      

$store_id = $_SESSION['store_id'];

$query = "SELECT * FROM brands WHERE store_id = '$store_id' AND accepted=1";
$result = mysqli_query($con,$query);

$response = array();
while($row = mysqli_fetch_array($result) ){
   $response[] = array("brand_name"=>$row['brand_name']);
}


echo json_encode($response);
?>

Below is the script that doesn’t work, the section defining the field:

<div class="form-group row">
    <div class="col-md-8">
        <label for="brand">Brand<span class="text-danger"> *</span></label>
        <div class="form-group">
            <div class="input-group">
                <input onClick="this.setSelectionRange(0, this.value.length);" type="text" 
                        class="js-autocompletebrand form-control uc_brand" id="filter_by_brand" name="filter_by_brand"
                        value="<?php echo $brand_name; ?>" placeholder="Enter brand name ...">
                <div class="input-group-append">
                    <button type="submit" class="btn btn-secondary">
                        <i class="fa fa-search"></i>
                    </button>
                    <?php if (((!empty($_POST['filter_by_brand'])) && (!empty($brand_id))) || 
                            ($brand_name == 'UNBRANDED')) { ?>
                        <span style="margin-left: 20px" class="font-size-h2 font-w700 text-success">
                            <i class="fa fa-check"></i>
                        </span>
                    <?php } ?>
                </div>
            </div>
        </div>                

    </div>
    <div class="col-md-12">                         
        <input type="hidden" class="form-control form-control-lg" id="brand-name" name="brand-name" value="<?php echo $brand_name; ?>">
        <span class="text-danger"  id="brand-err"></span>
    </div>
</div>

The above piece of code is the only one that differs from the other script, which works so I presume that this is the problem, not the js script itself. But I can’t find a fault with it.
Any help appreciated.

JS date functions show different date on different browsers

We have a date formatting function that seems to be producing different dates depending on browser. The function has two steps, first to determine the user’s date format, the second to format the date accordingly.

// determine date string format for PrettyDate functions
var dtstr;
var dtsep;
let customDate = new Date(2222, 11, 18);
let strDate = customDate.toLocaleDateString();
let daTyp = strDate.substring(0, 2);
if (daTyp === '22') {
  dtstr = 'YMD';
  dtsep = ',';
}
else if (daTyp === '12') {
  dtstr = 'MDY';
  dtsep = ';';
}
else {
  dtstr = 'DMY';
  dtsep = ',';
}

// make dates human readable
function prettyDate(datestr, use) {
  var date = new Date(datestr);
  if (!isNaN(date.getTime())) {
    const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    const monthCount = date.getMonth();
    const theMonth = monthNames[monthCount];
    const theYear = date.getFullYear();
    const theDay = date.getDate();
    if (use === 'short') {
      if (dtstr === 'MDY') {
        return theMonth + ' ' + theDay;
      }
      else {
        return theDay + ' ' + theMonth;
      }
    }
    else {
      if (dtstr === 'YMD') {
        return datestr;
      }
      else if (dtstr === 'MDY') {
        return theMonth + ' ' + theDay + ', ' + theYear;
      }
      else {
        return theDay + ' ' + theMonth + ' ' + theYear;
          }
    }
  }
}

The datestr being converted is of the format 2022-08-17 and the use value is either ‘short’ or ‘long’.

All the checks we have done on computers we have access to show the end date as 17 Aug 2022 or Aug 17 2022. But we have had several website users report they are getting 16 Aug 2022 or Aug 16 2022.

Do browsers interpret JS date function differently? I there something we missed to makes sure ALL browsers produce the same results from JS?

How to use an HTML template more than once [duplicate]

I created a bit of HTML in a template tag that I want to use from time to time in my webpage. I can get it to display once no problem, but if I try to add it elsewhere in the page it does not show up. I have included a much simplified version of the code below. Can someone enlighten me as to what I’m doing wrong?

var template = document.getElementById('testtemplate').content;

document.getElementById('firstDiv').appendChild(template);

document.getElementById('secondDiv').appendChild(template);
<template id='testtemplate'>
    <div class = calendarcontainer>
        <h1>hello</h1>
    </div>
</template>

<div id='firstDiv'></div>
<div id='secondDiv'></div>

Object is not displaying values in console log

My class objects are not displaying from the main object in the console log

// Inventory , the main class

class Inventory{
    constructor(shoe,customer){
        this.shoes = [];
        this.customers = [];
    }

    addShoes(shoe){
        this.shoes.push(shoe);
    }

    addCustomers(customer){
        this.customers.push(customer);
    }
}

// Customer class

class Customer{
    constructor(name,address,phone){
        this.name = name;
        this.address = address;  
        this.phone = phone;
    }
}

//Shoes class

class Shoes{
    constructor(brand,name,color,size){
        this.brand =  brand;
        this.name = name;
        this.colors = [];
        this.sizes = [];
    }

    addColors(color){
        this.colors.push(color);
    }

    addSizes(size){
        this.sizes.push(size);
    }
}

// Where I put in the data for the object values, to display to console log

const inventory = new Inventory();

const myko = new Customer("Myko","216 Peachtree",9144444444);

const shoes = new Shoes("Nike","Air Force 1");
      shoes.addColors(["Black/Green","Blue/white","Red/Blue","White/Red"]);
      shoes.addSizes([12,10,9,11]);


const newAdd = new Inventory(shoes,myko);

console.log(newAdd);

what my console log displays , empty data

Inventory {shoes: Array(0), customers: Array(0)}
customers: Array(0)


I want the console log to display , when I put in the data when I call the Inventory class in console.log

Inventory {shoes: Array(1), customers: Array(1)}

customers: “Myko” , “216 Peachtree” , 9144444444″

shoes: “Nike”, “Air Force 1”, “Black/Green”, “Blue/white”, “Red/Blue”, “White/Red”, 12, 10, 9, 11

Why is there a double quote at the beginning of the my result?

I have tried looking for this problem here but still can’t find an answer (maybe I’m too newbie to even write the exact keywords).
I am trying to overcome freecodecamp challenge on “binary agent”, my question is not “How to convert binary to text string” But

why is there a double quote at the beginning of the my result ?

Thank You

    function binaryAgent(str) {
  let binaryArr;
  let decimalArr = [];
  let textArr = [];
  let joinTextArr;
  for (let i=0; i<str.length; i++){
    // convert binary to decimal use parseInt(value, radix)
    binaryArr = str.split(" ");
    decimalArr.push(parseInt(binaryArr[i], 2));
    decimalArr = decimalArr.filter( value => !Number.isNaN(value) );
    // convert decimal to text
    textArr.push(String.fromCharCode(decimalArr[i]))
    // join to be a string
    joinTextArr = textArr.join("")
  }
  return joinTextArr;
}

console.log(binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111"));

// result > "Aren't bonfires fun!?