Why when breakpoint is present in my solution, the browser launched by the Javascript Debugger never actually resolve the page?

I found many post where breakpoint are not being it, but that is not the problem, the page simply never load. In the network tab, it says the initial request is pending and never complete.

If I open the same url on an other tabs in the same chrome, I have the same behavior but if I open the page on an other chrome window (off course debugging won’t work from there, unless I change de configuration to attach with some more settings) it does load. Which suggest that server is correctly running.

The chrome launched by the debugging is definately somewhat isolated to the normal installation (should be the default as I don’t think ive made any changes) which would explain the behavior only in this context.

However I do not know what can I look for this resolve this issue. This used to work and suddently stop working, I can’t says if due to a minor change in the configuration or update for the extention.

I have tried re-installing vscode, running vscode with –disable-extensions flag, without any success.

I have not seen any information related to this in the documentation here https://code.visualstudio.com/docs/nodejs/browser-debugging

launch.json for reference

{
      "name": "client",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:5000/app/",
      "webRoot": "${workspaceFolder}/angular-client"
}

I am running the ng build --deploy-url '/app/' --base-href '/app/' --output-path explaining the extra /app in the launch setting, this is an Angular App if relevant, back-end is .net core.

Anyone has an idea?
Thanks for the help

How to get just the node text, not the children’s text in puppeteer

Presume I the website layout looks like this:

<div id="monday">
  ...
  <div class="dish">
    Potato Soup
    <br>
    <span>With smoked tofu</span>
  </div>
</div>

How, using puppeteer, would I be able to grab just the text node’s content, not everything inside .dish?

I’ve tried

let selector = await page.waitForSelector("#monday .dish");
let text = await selector.evaluate(el => el.textContent) ?? "";

but that returns "Potato SoupWith smoked tofu"

PDF-Lib – React Native – Embed Images – image.scaleToFit Error Thrown

Attempting to embed image into form, following the pdf-lib specifications for jpg images.

This is how I attempted to do the task:

import { PDFDocument } from 'pdf-lib'
export async function createReport(images) {
    const formPdfBytes = await fetch(require('./assets/pdf/report_template.pdf')).then(res => res.arrayBuffer());
    const pdfDoc = await PDFDocument.load(formPdfBytes)
    const form = pdfDoc.getForm()
    let count = 0
    for (const i of images) {
        console.log(i)
        const fetched = await fetch(i.link, {mode: 'no-cors'}).then((res) => res.arrayBuffer())
        const image = pdfDoc.embedJpg(fetched)
        form.getButton('image.'+count).setImage(fetched)
        form.getTextField('blade_name.'+count).setText(i.name?.toString() || "")
        form.getTextField('blade_comments.'+count).setText(i.damage?.toString() + ". " + i.location?.toString() || "")
        count++
    }
    form.flatten();
    const uri = await pdfDoc.saveAsBase64({dataUri: true})
    console.log('File has been saved to:', uri);
}

This is the error thrown

TypeError: image.scaleToFit is not a function
    at ./node_modules/pdf-lib/es/api/form/PDFField.js.PDFField.createImageAppearanceStream (PDFField.js:338:1)
    at ./node_modules/pdf-lib/es/api/form/PDFButton.js.PDFButton.setImage (PDFButton.js:46:1)
    at pdf.js:81:1
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (asyncToGenerator.js:3:1)
    at _next (asyncToGenerator.js:22:1)
Uncaught (in promise) RangeError: Offset is outside the bounds of the DataView
    at DataView.getUint16 (<anonymous>)
    at Function.<anonymous> (JpegEmbedder.js:39:1)
    at step (tslib.es6.js:100:1)
    at Object.next (tslib.es6.js:81:1)
    at tslib.es6.js:74:1
    at new Promise (<anonymous>)
    at __awaiter (tslib.es6.js:70:1)
    at ./node_modules/pdf-lib/es/core/embedders/JpegEmbedder.js.JpegEmbedder.for (JpegEmbedder.js:35:1)
    at PDFDocument.<anonymous> (PDFDocument.js:958:1)

I’m not sure how to resolve. The same issue occurs when using the png method instead.

Links on Chrome extensions

I am using react to create a chrome extension but link functionality doesn’t seems to be working on the extension popup

<a
          href={`https://google.com`}
        >
          <Button>Click here</Button>
 </a>

How do I restart input? node.JS

I have two functions in which input is called
When I start the thread for the first time (first function), the second time it is no longer called (second function)

import * as readline from 'node:readline/promises';
import { stdin as input, stdout as output } from 'process';

const rl = readline.createInterface({input, output})

async function fffuncs (battlefield) {
    let input = await rl.question("Enter the first values: ");
    rl.close();
}

async function ssfuncs(battlefield) {
    rl.resume();
    let input = await rl.question("Enter the second values: ");
    rl.close();
}

fffuncs(battlefield).then(r => input)
ssfuncs(battlefield).then(r => input)

In the first function input is triggered and I enter values, but in the second function input no longer works

multiply user input values on click

I have this button along with these inputs, basically what happens when you click the button it changes the input values from the user and converts them to cm or inches.

<button type="button" id="change"> Display in centimeters</button>
<input type="radio" id="converter" checked="">

<div class="acf-input">
   <div class="acf-input-append">inches</div>
   <div class="acf-input-wrap">
    <input type="number" id="acf-field_640a56467e743" class="acf-is-appended" name="acf[field_640a56467e743]" value="187" step="any">
  </div>
</div>

<div class="acf-input">
   <div class="acf-input-append">inches</div>
   <div class="acf-input-wrap">
        <input type="number" id="acf-field_640a56467e743" class="acf-is-appended" name="acf[field_640a56467e743]" value="205" step="any">
   </div>
</div>

using this JQuery

$(document).on('click', ' #change', function(e) {
    if($('#converter').is(':checked')) {
      $("input[type=number]").each(function(){
       $("input[type=number]").val( $(this).html(parseFloat($(this).html()) * 2.54) ); 
      });
      $(".acf-input-append").each(function(){
        $(this).html($(this).html().replaceAll('inches', "cm"));
      });
      $('#change').html('Display in inches');
      $('#converter').prop('checked', false);
    } else {
      $("input[type=number]").each(function(){
        $("input[type=number]").val( $(this).html(parseFloat($(this).html()) / 2.54) );
      });
      $(".acf-input-append").each(function(){
        $(this).html($(this).html().replaceAll('cm', 'inches'));
      });
      $('#converter').prop('checked', true);
      $('#change').html('Display CM');
    }
  });

I’ve got the appended labels to change from inches to cm and then back, but the input values just go blank on click. How can I make sure they get multiplied by my set value (2.54 in this case)?

Thanks

AngularJS Data Mapping View Library

I have an AngularJS web app and I’d like to give the user the ability to link items in two distinct list visually similar to the image below.

enter image description here

I’ve been searching for a library that does this out of the box, but so far I have not found anything suitable. Has anyone run across this type of component? Does it have a technical term I can use to search better with?

Alpine js. How to dispatch a function to the store with a search parameter

I wonder how can dispatch a component function getAllProducts to the store with a search parameter and display the searched items in the components from API endpoint searched by the name key of the object array. The component code is written with search data attribute wich is sent to the store via $dispatch. But clicking on the Search button isn’t returning anything in the window. Trying to manage with Alpine js.

// html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="normalize.css" />
    <link rel="stylesheet" href="styles.css" />
    <script type="”module”" src="./script.js"></script>
    <title>Vesna</title>
  </head>

  <body>
    <section class="content">
      <div class="container">
        <div
          class="content__top"
          x-data="{
          search: ''
        }"
        >
          <input
            type="text"
            class="input font--m1"
            placeholder="Search for the item"
            x-model="search"
          />
          <button
            class="input__btn font--m1"
            @click="$dispatch('getAllProducts', search )"
          >
            Search
          </button>
        </div>
        <div class="content__mid-wrapper font--m2">
          <div x-data>
            <template x-for="item in $store.products.people" :key="item.id">
              <div class="content__mid">
                <p class="content__mid-item" x-text="item.name"></p>
                <p class="content__mid-item" x-text="item.email"></p>
                <p class="content__mid-item" x-text="item.username"></p>
              </div>
            </template>
          </div>
        </div>
      </div>
    </section>
  </body>
</html>

// script js

people: [],
  search: "",
  getAllProducts(searchInput) {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((response) => response.json())
      .then((res) => {
        if (this.searchInput) {
          this.people = res.results.filter((people) =>
            people.name.toLowerCase().includes(this.searchInput.toLowerCase())
          );
        } else {
          this.people = res.results;
        }
      });
  }

https://codesandbox.io/s/html-template-forked-ywqs9r?file=/script.js

Developing TypeScript package for Node.js, React and React Native (peerDependencies advice needed)

I am developing typescript package that should be used simple as “npm install ” for Node.js, React and RN.

Most of functionality of the package works in bare js without any problem, but also there is special files that should be used for react only or for RN only.

For example, if package is installed in React project, then user can import special hooks from /react folder.

Code separating is done in two ways: either using dynamic imports, either forcing the user to import part of the package himself (like with hooks, they are just here, not used if not imported by user)

Dynamic import usage example:

  private async _setupRN(config: PackageConfig) {
    const { subscribeForAppStateChanges } = await import("./rn");
    ...
    );
  };

  if (config?.enableReactNative) {
    this._setupRN(config);
  }

So, the problem:
If I just use the package by copying folder to ts-node / ts react / ts RN projects then everything works fine. (Even when using platform-specific functionality)

If I publish package to npm as it is (.ts files) and install it, then it works fine only in React Native. React, for example, throws errors on type definitions or import / export statements.

If I go all-in, and try to tsc –build package before uploading to npm (.js files) and install it, then it works fine in Node.js and React Native. But React project gives me this error:

Module not found: Error: Can't resolve 'react-native' in '.../node_modules/@appklaar/appklaar_sdk/rn'

And now, the most interesting:
Even If I completely remove import of files that uses react-native, so code that imports from ‘react-native’ should never be executed, I still get the same error. Looks like react is trying to require even unused files.

Why does it happen? How to fix it? react and react-native are my package’s peer dependencies. I have a guess that probably I am making tsx –build wrong way (it wont build if RN is just peer dependency, so i added it as devDependency also). But if thats the problem, then why in Node.js project everything works fine?

I am ok with making tsc –build every time when I want to update the package. I just want this to work everywhere.

I do not want to split package into 3 packages for each platform. I am completely sure that I am close to solution.

Package link if you want to check the code:
https://www.npmjs.com/package/@appklaar/appklaar_sdk
RN functionality is inside “rn” folder. Dynamic import is used in Connector file.
Version 1.4.12 was uploaded as .js files, version 1.4.13 was uploaded as .ts files.

Best practice for creating a dynamic horizontal bar chart using Spring, Thymeleaf and Javascript

Im relatively new to Spring and Thymeleaf but Ive managed to make a disc golf page showing the rounds played by a user with the courses and round scores shown in an accordion. Image below, I can dynamically add all the holes, pars, scores etc and it (so far) works good, but my javascript is still very much beginner.

I’m trying to add a simple horizontal stacked bar for each round, but so far I get only a chart on the first round, and most importantly, get the dynamic score data into the chart? Right now its hard coded in the javascript using the ‘const arr’.

So how can I have dynamic charts for each score card? Is it correct practice to pass the data using the th:attr?

Also I havent started trying to assign the color by score cause right now its hard coded. So like the score card, par is no color, 1 under par is blue, 1 over par is orange and a hole in one would be green.

html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link th:href="@{/css/fontawesome/css/all.css}" rel="stylesheet">
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap/bootstrap.min.css}"/>
    <link rel="stylesheet" th:href="@{https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css}">
    <link rel="stylesheet" type="text/css" th:href="@{/css/discgolf/round.css}">

    <title>Rounds</title>


</head>
<body>
<div th:replace="fragments/navbars/libraryNavbar :: navbar"></div>
<div class="container">
    <div class="subContainer">
        <h1>Rounds</h1>
        <a class="col-sm-4" th:href="@{/discgolf}">Disc Golf Home</a>
        <div class="row" id="username">
            <b class="col-sm-8">Username:<span sec:authentication="principal.username"></span></b>
        </div>
    </div>
    <a>Add Round</a>
    <form action="#" th:action="@{/discgolf/newRound}" th:object="${course}"
          method="GET">
        <div class="form-group">
            <div class="form-group blu-margin">
                <select th:name="course" class="form-control" onchange="this.form.submit()">
                    <option th:value="0" th:text="${'Please Select'}"></option>
                    <option th:each="course : ${courses}"
                            th:text="${course.name}" >

                    </option>
                </select>
            </div>
        </div>
    </form>
</div>
<div class="container">
    <div>
        <a>Rounds Played</a>
    </div>
    <div >
        <div th:each="roundCourse : ${rounds}" class="card">
            <button class="accordion">
                <span th:text="${roundCourse.key.name}"></span>

            </button>
            <div class="panel">
                <th:block th:each="round : ${roundCourse.value}">
                <div class="card-body">
                    <div class="row">
                        <div class="col-3">
                            <label>Date: </label>
                            <label th:text="${#dates.format(round.roundDate, 'dd-MMM-yyyy')}"></label>
                        </div>
                        <div class="col-3">
                            <label>Score: </label>
                            <label th:text="${round.total - round.course.par}"></label>
                        </div>
                        <div class="col-6">
                            <div class="container-fluid">
                                <canvas th:attr="data-counts=${round.scores}" id="myChart"></canvas>
                            </div>
                        </div>
                    </div>
                    <br>
                    <div >
                        <table id="courseInfo" class="table table-bordered w-auto">
                            <th:block th:each="course : ${round.course}">
                                <tr>
                                    <th th:text="${'Hole'}"></th>
                                    <th th:each="hole : ${course.holes}" th:text="${hole.number}"></th>
                                    <th th:text="${'Total'}"></th>
                                </tr>
                                <tr>
                                    <td th:text="${'Par'}"></td>
                                    <td th:each="par : ${course.holes}" th:text="${par.par}"></td>
                                    <td th:text="${course.par}"></td>
                                </tr>
                                <tr>
                                    <td th:text="${'Score'}"></td>
                                    <th:block th:each="score : ${round.scores}">

                                        <td th:style="${score.score > score.holePar}
                                    ? 'background-color: red'
                                    : (${score.score < score.holePar } ? 'background-color: blue'
                                    : 'background-color: #eee' ) " th:text="${score.score}"></td>
                                    </th:block>
                                    <td th:text="${round.total}"></td>
                                </tr>
                            </th:block>
                        </table>
                        <br>
                        <a th:href="@{/discgolf/deleteRound/{id}(id=${round.roundId})}" title="Remove Course"
                           data-target="#deleteRoundModal" class="table-link danger" id="deleteRoundButton" >
                            <span id="deleteRound" class="fa-stack">
                                <i class="fa fa-square fa-stack-2x"></i>
                                <i class="fa fa-trash-o fa-stack-1x fa-inverse" title="Delete this round"></i>
                            </span>
                        </a>
                    </div>
                </div>
                <hr>
                </th:block>
            </div>
        </div>
    </div>
</div>
<script th:inline="javascript">
    var listRounds = [[${rounds}]];

</script>
<script>


</script>

<!--<div th:replace="/discgolf/fragments/deleteCourseModal :: deleteCourseModal"></div>-->


<script type="text/javascript" src="/js/jquery-3.6.0.js"></script>
<script type="text/javascript" src="/js/bootstrap/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script th:src="@{/js/discgolf/userRounds.js}"></script>
</body>
</html>

javascript

const countsTest = document.getElementById('myChart').getAttribute('data-counts');
console.log("Counts Test: " + countsTest);

*** so the dynamic array would be here***
const arr = [3, 3, 4, 2, 2, 3, 3, 2, 4, 4];
const counts = {};

for (const num of arr) {
  counts[num] = counts[num] ? counts[num] + 1 : 1;
}

console.log(counts);
console.log(counts[1], counts[2], counts[3], counts[4], counts[5]);


var acc = document.getElementsByClassName("accordion");
var i;

for (i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var panel = this.nextElementSibling;
    if (panel.style.maxHeight) {
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    }
  });
}


  new Chart(document.getElementById('myChart'),{
      type: 'bar',
      options: {
        responsive: true,
        maintainAspectRatio: false,
        indexAxis: 'y',
        scales: {
          x: {
            stacked: true,
            display: false
          },
          y: {
            stacked: true,
            display: false
          }
        },
        plugins: {
          legend: {
            display: false
          }
        },
      },

      data: {
        labels: ["Score"],

        datasets: [{
          data: [counts[2]],
          backgroundColor: "#77ACD8"

        },{
          data: [counts[3]]
//          backgroundColor: "rgba(163,103,126,1)"
        },{
          data: [counts[4]],
          backgroundColor: "#FDC169"
        }]
      }
    }
  );

Controller

@GetMapping("/rounds/{id}")
    public String roundsHome(@PathVariable(value = "id") Long id,
                             Model model) {
        List<Course> courses = courseService.getAllCourses();
        List<Round> rounds = userService.getUserById(id).getRounds();
        Map<Course, List<Round>> mapRoundsByCourse = rounds.stream().collect(Collectors.groupingBy(Round::getCourse));
        model.addAttribute("courses", courses);
        model.addAttribute("rounds", mapRoundsByCourse);
        return "/discgolf/round/rounds";
    }

Data

Course{id=2, name='Ilsede', holes=[Hole{holeId=46, number=1, par=3}, Hole{holeId=47, number=2, par=3}, Hole{holeId=48, number=3, par=3}, Hole{holeId=49, number=4, par=3}, Hole{holeId=50, number=5, par=3}, Hole{holeId=51, number=6, par=3}, Hole{holeId=52, number=7, par=3}, Hole{holeId=53, number=8, par=3}, Hole{holeId=54, number=9, par=3}, Hole{holeId=55, number=10, par=3}, Hole{holeId=56, number=11, par=3}, Hole{holeId=57, number=12, par=3}, Hole{holeId=58, number=13, par=4}, Hole{holeId=59, number=14, par=3}, Hole{holeId=60, number=15, par=3}, Hole{holeId=61, number=16, par=3}, Hole{holeId=62, number=17, par=3}, Hole{holeId=63, number=18, par=3}], par=55, record=7}
        =[Round{roundId=21, course=Course{id=2, name='Ilsede', holes=[Hole{holeId=46, number=1, par=3}, Hole{holeId=47, number=2, par=3}, Hole{holeId=48, number=3, par=3}, Hole{holeId=49, number=4, par=3}, Hole{holeId=50, number=5, par=3}, Hole{holeId=51, number=6, par=3}, Hole{holeId=52, number=7, par=3}, Hole{holeId=53, number=8, par=3}, Hole{holeId=54, number=9, par=3}, Hole{holeId=55, number=10, par=3}, Hole{holeId=56, number=11, par=3}, Hole{holeId=57, number=12, par=3}, Hole{holeId=58, number=13, par=4}, Hole{holeId=59, number=14, par=3}, Hole{holeId=60, number=15, par=3}, Hole{holeId=61, number=16, par=3}, Hole{holeId=62, number=17, par=3}, Hole{holeId=63, number=18, par=3}], par=55, record=7}, scores=[Score{scoreId=199, score=3, holePar=3}, Score{scoreId=200, score=3, holePar=3}, Score{scoreId=201, score=3, holePar=3}, Score{scoreId=202, score=4, holePar=3}, Score{scoreId=203, score=3, holePar=3}, Score{scoreId=204, score=3, holePar=3}, Score{scoreId=205, score=2, holePar=3}, Score{scoreId=206, score=3, holePar=3}, Score{scoreId=207, score=3, holePar=3}, Score{scoreId=208, score=4, holePar=3}, Score{scoreId=209, score=3, holePar=3}, Score{scoreId=210, score=3, holePar=3}, Score{scoreId=211, score=2, holePar=3}, Score{scoreId=212, score=3, holePar=3}, Score{scoreId=213, score=3, holePar=3}, Score{scoreId=214, score=4, holePar=3}, Score{scoreId=215, score=3, holePar=3}, Score{scoreId=216, score=2, holePar=3}], roundDate=2023-03-01 00:00:00.0, total=54},
        Round{roundId=24, course=Course{id=2, name='Ilsede', holes=[Hole{holeId=46, number=1, par=3}, Hole{holeId=47, number=2, par=3}, Hole{holeId=48, number=3, par=3}, Hole{holeId=49, number=4, par=3}, Hole{holeId=50, number=5, par=3}, Hole{holeId=51, number=6, par=3}, Hole{holeId=52, number=7, par=3}, Hole{holeId=53, number=8, par=3}, Hole{holeId=54, number=9, par=3}, Hole{holeId=55, number=10, par=3}, Hole{holeId=56, number=11, par=3}, Hole{holeId=57, number=12, par=3}, Hole{holeId=58, number=13, par=4}, Hole{holeId=59, number=14, par=3}, Hole{holeId=60, number=15, par=3}, Hole{holeId=61, number=16, par=3}, Hole{holeId=62, number=17, par=3}, Hole{holeId=63, number=18, par=3}], par=55, record=7}, scores=[Score{scoreId=244, score=3, holePar=3}, Score{scoreId=245, score=3, holePar=3}, Score{scoreId=246, score=3, holePar=3}, Score{scoreId=247, score=3, holePar=3}, Score{scoreId=248, score=4, holePar=3}, Score{scoreId=249, score=3, holePar=3}, Score{scoreId=250, score=3, holePar=3}, Score{scoreId=251, score=3, holePar=3}, Score{scoreId=252, score=2, holePar=3}, Score{scoreId=253, score=3, holePar=3}, Score{scoreId=254, score=3, holePar=3}, Score{scoreId=255, score=3, holePar=3}, Score{scoreId=256, score=2, holePar=3}, Score{scoreId=257, score=3, holePar=3}, Score{scoreId=258, score=3, holePar=3}, Score{scoreId=259, score=4, holePar=3}, Score{scoreId=260, score=3, holePar=3}, Score{scoreId=261, score=3, holePar=3}], roundDate=2023-03-09 00:00:00.0, total=54}]

Image of roundId = 21 (I know colors dont match yet)
enter image description here

Thanks in advance

Hiw can i make multiple redirections

i am trying to make the visitor go to url then the another and not stop after he go to one site or go to site from list randomly

**itried this **

<script>
function redirect(){
windows.open("facebook.com")
windwos.open("google.com")
windwos.open("instagram.com")
}
</script>

<body onload="redirect()">

but it is not working

Canvas Image export error (Tainted canvases may not be exported)

I am trying to export the images from my canvas but I am getting the console error (Tainted canvases may not be exported) on Chrome.

I need to get the final image merged in BASE64
My backend is in asp net 6 and my source images will be in base64.

My code is working here but when I use it in html file I am getting this error. How can I fix it?

To replicate you just need to insert 4 LOCAL images in getImage(), when I use HTTPS images it works, i need to use base64 image.

var canvas, context;
var image1 = new Image();
var image2 = new Image();
var image3 = new Image();



var isDraggable = false;

var currentX = 0;
var currentY = 0;

function _Load() {
  canvas = document.getElementById("canvas");
  context = canvas.getContext("2d");



  currentX = canvas.width/2;
  currentY = canvas.height/2;

  image1.onload = function() {
    _Go();
  };

  image2.onload = function() {
    _Go();
  };

  image3.onload = function() {
    _Go();
  };

  image1.src = getImage('plane');
  image1.visible = true; 

  image2.src = getImage('banana');
  image2.visible = false;

  image3.src = getImage('pikachu');
  image3.visible = false;

}

function _Go() {
    _MouseEvents();
  
    setInterval(function() {
      _ResetCanvas();
      _DrawImage();
    }, 1000/30);
}

function _MouseEvents() {
canvas.onmousedown = function(e) {

  var mouseX = e.pageX - this.offsetLeft;
  var mouseY = e.pageY - this.offsetTop;


  if (mouseX >= (currentX - image2.width/2) &&
      mouseX <= (currentX + image2.width/2) &&
      mouseY >= (currentY - image2.height/2) &&
      mouseY <= (currentY + image2.height/2)) {
    isDraggable = true;
    //currentX = mouseX;
    //currentY = mouseY;
  }

  if (mouseX >= (currentX - image3.width/2) &&
      mouseX <= (currentX + image3.width/2) &&
      mouseY >= (currentY - image3.height/2) &&
      mouseY <= (currentY + image3.height/2)) {
    isDraggable = true;
    //currentX = mouseX;
    //currentY = mouseY;
  }
};
canvas.onmousemove = function(e) {

  if (isDraggable) {
    currentX = e.pageX - this.offsetLeft;
    currentY = e.pageY - this.offsetTop;
  }
};
canvas.onmouseup = function(e) {
  isDraggable = false;
};
canvas.onmouseout = function(e) {
  isDraggable = false;
};
}

function _ResetCanvas() {
    context.fillStyle = '#fff';
    context.fillRect(0,0, canvas.width, canvas.height);
}

function _DrawImage() {

if(image2.visible){
    context.drawImage(image1, 0, 0, 500, 500);
    context.drawImage(image2, currentX-(image2.width/2), currentY-(image2.height/2));
  }else if(image3.visible){
    context.drawImage(image1, 0, 0, 500, 500);
    context.drawImage(image3, currentX-(image3.width/2), currentY-(image3.height/2),);
  }else{
    context.drawImage(image1, 0, 0, 500, 500);
  }
};

function _CleanCanvas(){
    
    image1.visible = true;
    image2.visible = false;
    image3.visible = false;  
    _DrawImage();
}

function _WatermarkAdd(item){
    switch(item) {
        case 'roi':
            image2.src = getImage('banana');
            image2.visible = true;
            _ResetCanvas();
            _DrawImage()
          break;
        case 'ni':
            image2.src = getImage('pikachu');
            image2.visible = true;
            _ResetCanvas();
            _DrawImage()
          break;
      }
}

function _ChangeImage(){
    image1.src = 'secondary.jpg';
    _ResetCanvas();
    _DrawImage(); 
}

function _MergeImages(){
 
    var dataURL = canvas.toDataURL("image/png");
    console.log(dataURL);
}

function getImage(imageName){

  switch(imageName) {
    case 'banana':
        return "banana.jpg"
      break;
      case 'pikachu':
        return "pikachu.jpg"
      break;
      case 'plane':
        return "primary.jpg"
      break;
      case 'plane2':
        return "secondary.jpg"
      break;
    }
} 
<h1>Click Image then Drag</h1>
<canvas id="canvas" width="500" height="500" style="border: 1px solid black"></canvas>
<button onclick="_CleanCanvas()">Reset</button>
<button onclick="_Load()">Load</button>
<button onclick='_WatermarkAdd("roi")'>ROI</button>
<button onclick='_WatermarkAdd("ni")'>NI</button>
<button onclick='_MergeImages()'>Merge</button>

Best practices while separating Frontend from Backend [closed]

So I’ve been working on a web application in codeigniter. I’ve followed the MVC model to keep things as they stated(processing in controller,sql stuff in model and visble things in views) . However I’m not sure how exactly frontend and backend are to be separated and what kind of data I should allow in Views files.

Even a general guideline or something specific to codeigniter will do as well.

The data I’m sending to views rn are the login details for editing their profile and some database data that the person seeing that view needs to see.

My current views files are written almost entirely in html and php with minor js functions(only for some buttons that change UI) . Should I convert all the php stuff(displaying tables,loading data from controller etc.)in views to JS?