Using Angular’s Custom Elements

I have to build a web component to inject inside a legacy code project;
I tried to follow the official documentation to do so using angular (https://v19.angular.dev/guide/elements) but I feel like is a bit incomplete: for example there is nothing about how do produce a js file to then refer in the html of the target project to be able to use the custom html tag.

I searched extensively for guides or more about the topic but nothing pops out on the Internet, at least not for the newer versions of Angular (newest stuff I found was 2 year old).

I followed the official guide ’till the end and tried to ng build and use the main.js and polyfill.js inside of an html file to reference the custom html tag created in Angular
but I get the following error that is not so explanatory.

enter image description here

Anyone out there building web components in angular that’s facing my same troubles?

This is my app.component.ts:
enter image description here

This is my notifications-center.ts and html;
enter image description here

enter image description here

As you can tell the component is default just because I wanted to test stuff before actually starting the developing.

This is the html file where I’m trying to use the web-component:
enter image description here

Why does my if statement that compares two characters return false when both characters are the same? [closed]

I wrote some code originally to test the eval() function, but now I’m turning it into a very basic calculator. Since it uses the eval() function to calculate the expressions entered in the input <textarea>, I had to make a system that prevents users from putting javascript code into the input and executing it (I think that’s what XSS is). To do this, I made a nested for loop that takes the input and uses charAt() to compare each character in the input to a each character in the disallowedChars string. If the two characters are the same, it’s supposed to set valid to false and break out of the entire loop (the parent loop is labelled charTest). If valid is true, it then uses eval() to evaluate the expression entered in the input, otherwise, it doesn’t.

The problem is that for some reason, the code doesn’t work. For example, if I input the string 2**63, it outputs 9,223,372,036,854,776,000. However if I input 1A, you’ll see that one of the things the console outputs is A is not A Approved! when they are both the same. I’m not using characters from another alphabet (like Greek or Cyrillic), as you’ll be able to check easily for yourself. Here’s all my code:

const expr = document.querySelector("#expr");
const result = document.querySelector("#result");

function calculate() {
  const disallowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`~!@#$%^&_=[]\{}|;':",./<>?";
  var input = expr.value;
  var valid = true;
  if (input != "") {
    charTest: for (var k = 0; k < input.length; k++) {
      console.log("The current character being checked is " + input.charAt(k) + " at position " + k);
      for (var i = 0; i < disallowedChars.length; i++) {
        console.log("Comparing " + input.charAt(k) + " at position " + k + " to " + disallowedChars.charAt(i) + " at position " + i);
        if (input.charAt(k) == disallowedChars.charAt[i]) {
          console.error("Denied");
          alert("For safety purposes, the character "" + input.charAt(k) + "" is not allowed");
          valid = false;
          break charTest;
        } else {
          console.log(input.charAt(k) + " is not " + disallowedChars.charAt(i));
          console.log("Approved!");
        }
      }
    }
    if (valid) {
      var resultText = new Number(eval(input)).toLocaleString();
      result.value = resultText;
    } else {
      alert("Failed to calculate expression")
    }
  } else {
    alert("Enter a valid expression");
  }
}

function resetHeights() {
  expr.style.height = result.style.height = "12.5vh"
}
<!DOCTYPE html>
<html>
  <head>
    <title>eval() test</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./styles.css">
  </head>
  <body>
    <textarea name="expr" id="expr" placeholder="Enter a mathematical expression..."></textarea>
    <textarea name="result" id="result" placeholder="Result will appear here..." disabled></textarea>
    <br>
    <button onclick="calculate()">Calculate</button>
    <button onclick="resetHeights()">Reset heights</button>
    <button onclick="location.reload()">Reset</button>
    <h6 class="h0">Allowed symbols:</h6>
    <ul>
      <ol><code>+</code> — addition</ol>
      <ol><code>-</code> — subtraction</ol>
      <ol><code>*</code> — multiplication</ol>
      <ol><code>/</code> — division</ol>
      <ol><code>**</code> — exponentiation</ol>
      <ol><code>()</code> — parentheses for grouping</ol>
    </ul>
    <script src="./main.js"></script>
  </body>
</html>

I’ve tried to figure it out myself for a total of around an hour, but I just couldn’t find where I may have messed up. Does anyone know what the issue might be and how I could go about fixing it?


(p.s. I hope this was one of my better Stack Overflow questions, I’ve asked pretty bad questions in the past. If anyone cares to do so, I’d appreciate feedback on the post itself because I’m still learning how to ask good questions on Stack Overflow)

vis.js shows items with no time starting at around 8PM instead of midnight

Just starting to play with vis.js, timeline mode. Going through the demos, and have everything working. However, when I zoom in on at object on CodePen, dates (without time) start at midnight, which is what you expect. On my computer, dates without time seem to start around 8 PM. In order to get it to start at midnight, i have to explicitly set the time at 00:00. I have tried both 4.19.1 and 4.21.0. I have also tried both Brave and Google Chrome.
The specific example I am trying is one codePen.

https://visjs.github.io/vis-timeline/examples/timeline-generated/codepen.3dc7091f5e57b7311a29e191620f46f17a8f393ee333be69f9391d5869de5ec0.html

When I copy this to my computer, while all nodes show correct, instead of starting at midnight, all start at around 8PM. I have to change the demo code of

var items = new vis.DataSet([
  {
    id: 1,
    content: "item 1 with overflowing text content",
    start: "2014-04-20",
    end: "2014-04-26",
  }, 

to

var items = new vis.DataSet([
  {
    id: 1,
    content: "item 1 with overflowing text content",
    start: "2014-04-20 00:00",
    end: "2014-04-26 00:00",
  },

Any idea why this is happening?

** Additional Info: The Codepen is using a different version of vis.js., which is https://visjs.github.io/vis-timeline/standalone/umd/vis-timeline-graph2d.min.js

Using Docxtemplater horizontally expand nested loop in a MS Word Table

We have data that looks like this:

[
  {
    firstName: 'Susan',
    lastName: 'Storm'
    meta: [
      {
        age: 30,
        email: '[email protected]'
      }
    ]
  },
  {
    firstName: 'Peter',
    lastName: 'Parker'
    meta: [
      {
        age: 30,
        email: '[email protected]'
      }
    ]
  }
]

We are trying to build an MS Word document with a table that includes the following columns:

First Name, Last Name, Age, Email
Susan, Storm, 30, [email protected]
Peter, Parker, 30, [email protected]

We have tried using multi-level loops using both the Vertical Table module and the built-in looping.

Any suggestions on how to achieve this in a Word document using Docxtemplater?

Rotate a label in Plotly Treemap with JavaSctipt

Sometimes there’re narrow bricks on treemaps. Plotly decrease the font size of such a labels, so you cannot read them. But another way is making thease labels horizontal. As far as I understood the only way to rotate labels in Plotly is using JavaScript. I’m new at it, please help to understand how to select some particular node with JS?
Here’s the example code, where I try to rotate the label ‘a1’ (but fail):

data = {'level1': ['A', 'A', 'B', 'B'], 'level2': ['a1', 'a2', 'b1', 'b2']}
fig = px.treemap(data, path=['level1', 'level2'])

js = """
   function rotateLabel(){
       const nodes = gd.querySelectorAll('slicetext');
       for (const node of nodes){
            const label = node.querySelector('[data-unformatted="a1"]');
            label.style.transform = 'rotate(90deg)';
       }
   }       
   const gd = document.querySelector('.plotly-graph-div');
   gd.on('plotly_afterplot', rotateLabel.bind(gd));
   gd.emit('plotly_afterplot');
   
   """

fig.show(post_script=[js])

How to add own pathfinder in GitHub PathFinding.js repository?

I have forked PathFinding.js and have added the IDDFS pathfinder. (It is based on this Java implementation.)

I followed some arbitrary guidelines and made it visible in the visual/index.html, yet it throws an error as soon as I press the Start Search button:

state-machine.min.js:1 Uncaught TypeError: Cannot read properties of undefined (reading 'findPath')
onsearch    @   controller.js:138
doCallback  @   state-machine.min.js:1
afterEvent  @   state-machine.min.js:1
transition  @   state-machine.min.js:1
(anonymous) @   state-machine.min.js:1
onstarting  @   controller.js:230
doCallback  @   state-machine.min.js:1
enterState  @   state-machine.min.js:1
transition  @   state-machine.min.js:1
(anonymous) @   state-machine.min.js:1
g   @   jquery-1.7.2.min.js:2
dispatch    @   jquery-1.7.2.min.js:3
i   @   jquery-1.7.2.min.js:3

Registration form not displaying validation error messages for input fields

I’m building a user registration form using HTML, CSS, and JavaScript, with Firebase Authentication handling the registration.

I wanted to add a common feature where errors are prompted when using an invalid email, a short password, or mismatched passwords. This is quite common with many registration forms.

I expected inline error messages like “Invalid email format” or “Passwords do not match”) to appear under the form fields when validation fails. For some reason, it doesn’t show up or give that prompt. It’s as if the JS doesn’t trigger to show that.

const form = document.getElementById('register-form');
const emailInput = document.getElementById('email');
const passwordInput = document.getElementById('password');
const repeatPasswordInput = document.getElementById('repeat-password');

function resetErrors() {
  [emailInput, passwordInput, repeatPasswordInput].forEach(input => {
    input.classList.remove('error');
    document.getElementById(`${input.id}-error`).classList.remove('show');
  });
}

function validateInputs() {
  let hasError = false;
  resetErrors();

  if (!emailInput.value.includes('@') || !emailInput.value.includes('.')) {
    emailInput.classList.add('error');
    document.getElementById('email-error').classList.add('show');
    hasError = true;
  }

  if (passwordInput.value.length < 6 || passwordInput.value.length > 32) {
    passwordInput.classList.add('error');
    document.getElementById('password-error').classList.add('show');
    hasError = true;
  }

  if (passwordInput.value !== repeatPasswordInput.value) {
    repeatPasswordInput.classList.add('error');
    document.getElementById('repeat-password-error').classList.add('show');
    hasError = true;
  }

  return !hasError;
}

form.addEventListener('submit', (e) => {
  e.preventDefault();
  if (!validateInputs()) {
    alert('Please fix the highlighted fields.');
  } else {
    alert('Form submitted!');
    form.reset();
    resetErrors();
  }
});
.register-container {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 4rem;
  padding: 5rem 2rem;
  max-width: 1100px;
  margin: 0 auto;
  flex-wrap: wrap;
}

#register-form {
  flex: 1;
  max-width: 400px;
  background-color: #fcfcfc;
  padding: 2rem 2.5rem;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(122, 132, 80, 0.2);
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  box-sizing: border-box;
}



#register-form label {
  display: block;
  margin-bottom: 0.3rem;
  font-weight: 600;
  color: #4b5221;
}

#register-form input {
  width: 100%;
  padding: 0.6rem 0.8rem;
  margin-bottom: 1rem;
  border: 1.5px solid #c8ceaa;
  border-radius: 6px;
  font-size: 1rem;
  transition: border-color 0.3s ease;
}

#register-form input:focus {
  border-color: #7a8450;
  outline: none;
}

#submit {
  width: 100%;
  background-color: #7a8450;
  border: none;
  color: white;
  font-weight: 700;
  padding: 0.75rem;
  border-radius: 25px;
  font-size: 1.1rem;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.form {
  text-align: center;
  margin-top: 1.5rem;
  font-size: 0.95rem;
  color: #555;
}

.form a {
  color: #7a8450;
  font-weight: 600;
  text-decoration: none;
}

.form a:hover {
  text-decoration: underline;
}

.register-tip {
  font-size: 0.8rem;
  color: #7a8450;
  font-style: italic;
  margin-top: 0rem;
  margin-bottom: 1rem;
}

input.error {
  border: 2px solid red;
  background-color: #ffe6e6;
}

.error-message {
  color: red;
  font-size: 0.8rem;
  margin-top: 0rem;
  margin-bottom: 0.2rem;
  display: none;
}

#register-form .error-message.show {
  display: block;
}


@media screen and (max-width: 768px) {
  .register-container {
    padding: 2rem 1rem;
  }

  #register-form,
  .register-info {
    max-width: 100%;
  }
}
<form id="register-form">
  <label for="email">Email</label>
  <input type="email" id="email" placeholder="Email" />
  <div class="error-message" id="email-error">Please enter a valid email</div>

  <label for="password">Password</label>
  <input type="password" id="password" placeholder="Password" />
  <div class="error-message" id="password-error">Password too short</div>

  <label for="repeat-password">Repeat Password</label>
  <input type="password" id="repeat-password" placeholder="Repeat Password" />
  <div class="error-message" id="repeat-password-error">Passwords do not match</div>

  <button type="submit">Register</button>
</form>
  • I added console.log to confirm validateInputs runs (it sends the reports as intended).
  • Checked CSS for conflict. The displays should be correct.

“navigator.clipboard.writeText fails if tab loses focus — workaround?”

I’m using navigator.clipboard.writeText() to copy decrypted content after a button click.

The value is decrypted asynchronously (Promise / Observable in Angular), and once decrypted, I attempt to copy it to clipboard.

Problem

In practice, users click the “Copy” button and immediately switch to another app (like Notepad) or browser tab to paste the value.

This causes the document to lose focus before the asynchronous decryption completes, and the clipboard operation fails.

UX Issue

As a result — the copy silently fails, and the user ends up pasting nothing.

This is especially problematic because they don’t see the error, and it feels like the button is broken.

I understand this is a browser limitation for security reasons.

Are there any workarounds ? What should I do in this situation?
Here is my current implementation

 public copySecureField(key: keyof SecureInfoFields, value: string): void {
    this.getDecryptedDataForCopying({ [key]: value })
      .pipe(
        switchMap((data) => {
          return from(navigator.clipboard.writeText(data[key])).pipe(
            catchError(() => {
              this._notificationService.error(COPY_FAIL_FOCUS_MESSAGE);

              return EMPTY;
            }),
          );
        }),
        tap(() => this.setSecureFieldIsCopied(key, true)),
        delay(1000),
        finalize(() => this.setSecureFieldIsCopied(key, false)),
      )
      .subscribe();
  }

Laravel/Filament gave HTTP 500 after edit an resource

I got problems with a Laravel/Filament Project. I can create Filament Resources and view, but as soon as i do any action like creating, editing or deleting it performs that action and afterwards i got HTTP 500 error. It’s regardless, wich filament page I try to open. Even on a complete new installation this happens.

I found out: If I delete my session and I log in completly new, it works again. So I assume it’s a session problem, but I left everything by default.

My setup:

.env

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:EaR7VEAw8oTwAoVsJkTEb33EWYnMMPsHL87EWeL9xFc=
APP_DEBUG=true
APP_URL=http://localhost

APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US

APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database

PHP_CLI_SERVER_WORKERS=4

BCRYPT_ROUNDS=12

LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=test
DB_USERNAME=x
DB_PASSWORD=x

SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null

BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database

CACHE_STORE=database
# CACHE_PREFIX=

MEMCACHED_HOST=127.0.0.1

REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=log
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

VITE_APP_NAME="${APP_NAME}"

composer

name     : filament/filament
descrip. : A collection of full-stack components for accelerated Laravel app development.
keywords :
versions : * v3.3.0
released : 2025-02-25, 4 months ago
type     : library
license  : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage : https://github.com/filamentphp/filament
source   : [git] https://github.com/filamentphp/panels.git 2ddea9d4c3c7d1bfce2d9ea6b3d7d7fe8c5682ec
dist     : [zip] https://api.github.com/repos/filamentphp/panels/zipball/2ddea9d4c3c7d1bfce2d9ea6b3d7d7fe8c5682ec 2ddea9d4c3c7d1bfce2d9ea6b3d7d7fe8c5682ec     
path     : C:UserskwagnerDesktoptestvendorfilamentfilament
names    : filament/filament

support
issues : https://github.com/filamentphp/filament/issues
source : https://github.com/filamentphp/filament

autoload
files
psr-4
Filament => src

requires
danharrin/livewire-rate-limiting ^0.3|^1.0|^2.0
filament/actions self.version
filament/forms self.version
filament/infolists self.version
filament/notifications self.version
filament/support self.version
filament/tables self.version
filament/widgets self.version
illuminate/auth ^10.45|^11.0|^12.0
illuminate/console ^10.45|^11.0|^12.0
illuminate/contracts ^10.45|^11.0|^12.0
illuminate/cookie ^10.45|^11.0|^12.0
illuminate/database ^10.45|^11.0|^12.0
illuminate/http ^10.45|^11.0|^12.0
illuminate/routing ^10.45|^11.0|^12.0
illuminate/session ^10.45|^11.0|^12.0
illuminate/support ^10.45|^11.0|^12.0
illuminate/view ^10.45|^11.0|^12.0
php ^8.1
spatie/laravel-package-tools ^1.9
name     : livewire/livewire
descrip. : A front-end framework for Laravel.
keywords : 
versions : * v3.6.4
released : 2025-07-17, this week
type     : library
license  : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage :
source   : [git] https://github.com/livewire/livewire.git ef04be759da41b14d2d129e670533180a44987dc
dist     : [zip] https://api.github.com/repos/livewire/livewire/zipball/ef04be759da41b14d2d129e670533180a44987dc ef04be759da41b14d2d129e670533180a44987dc      
path     : C:UserskwagnerDesktoptestvendorlivewirelivewire
names    : livewire/livewire

support
issues : https://github.com/livewire/livewire/issues
source : https://github.com/livewire/livewire/tree/v3.6.4

autoload
files
psr-4
Livewire => src/

requires
illuminate/database ^10.0|^11.0|^12.0
illuminate/routing ^10.0|^11.0|^12.0
illuminate/support ^10.0|^11.0|^12.0
illuminate/validation ^10.0|^11.0|^12.0
laravel/prompts ^0.1.24|^0.2|^0.3
league/mime-type-detection ^1.9
php ^8.1
symfony/console ^6.0|^7.0
symfony/http-kernel ^6.2|^7.0

requires (dev)
calebporzio/sushi ^2.1
laravel/framework ^10.15.0|^11.0|^12.0
mockery/mockery ^1.3.1
orchestra/testbench ^8.21.0|^9.0|^10.0
orchestra/testbench-dusk ^8.24|^9.1|^10.0
phpunit/phpunit ^10.4|^11.5
psy/psysh ^0.11.22|^0.12

php.ini

engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
zend.enable_gc = On
zend.exception_ignore_args = Off
zend.exception_string_param_max_len = 15
expose_php = On
max_execution_time = 30
max_input_time = 60
memory_limit = 128M
error_reporting = E_ALL
display_errors = On
display_startup_errors = On
log_errors = On
ignore_repeated_errorsl = Off
ignore_repeated_source = Off
report_memleaks = On
error_log = "M:phplogsphp_errors.log"
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 8M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =
extension_dir = "ext"
enable_dl = Off
file_uploads = On
upload_max_filesize = 2M
max_file_uploads = 20
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
extension=curl
extension=fileinfo
extension=intl
extension=ldap
extension=mbstring
extension=openssl
extension=pdo_mysql
extension=zip
cli_server.color = On
pdo_mysql.default_socket=
SMTP = localhost
smtp_port = 25
mail.add_x_header = Off
mail.mixed_lf_and_crlf = Off
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = On
mysqlnd.mempool_default_size = 16000
mysqlnd.net_cmd_buffer_size = 2048
mysqlnd.net_read_buffer_size = 32768
mysqlnd.net_read_timeout = 31536000
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
bcmath.scale = 0
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.trans_sid_tags = "a=href,area=href,frame=src,form="
zend.assertions = 1
tidy.clean_output = Off
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
ldap.max_links = -1
mysqli.default_port = 3306

pushManager.subscribe return null on android firefox (not working at all on chrome)

i’m trying to create a simple web push notif using service worker, it works well on browsers in desktop, but on android device not working!

on firefox android: pushManager.subscribe() return null
on chrome android, it doesnt even reach to subscribe stage

index.php file:

<?php
require __DIR__ . '/vendor/autoload.php';

use MinishlinkWebPushVAPID;

// Generate VAPID keys if they don't exist
$vapidFile = __DIR__ . '/vapid.json';
if (!file_exists($vapidFile)) {
    $keys = VAPID::createVapidKeys();
    file_put_contents($vapidFile, json_encode($keys));
} else {
    $keys = json_decode(file_get_contents($vapidFile), true);
}

// Save subscription if POST request
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    var_dump(file_get_contents('php://input'));
    var_dump(__DIR__);
    file_put_contents(__DIR__ . '/subscription.json', file_get_contents('php://input'));
    echo 'Subscription saved';
    exit;
}
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Push Demo</title>
</head>
<body>
  <h2>Web Push Demo</h2>
  <button id="subscribeBtn">Subscribe for Push</button>

  <script>
    const publicKey = '<?= $keys['publicKey'] ?>';

    function urlBase64ToUint8Array(base64String) {
       // Ensure correct padding
      const padding = '='.repeat((4 - base64String.length % 4) % 4);
      const base64 = (base64String + padding)
        .replace(/-/g, '+')
        .replace(/_/g, '/');

      const rawData = atob(base64);
      const buffer = new Uint8Array(rawData.length);

      for (let i = 0; i < rawData.length; ++i) {
        buffer[i] = rawData.charCodeAt(i);
      }
      return buffer;
    }

    async function subscribe() {
      try{
        const permission = await Notification.requestPermission();
        if (permission !== 'granted') {
          alert('Please enable notifications!');
          return;
        }

        const reg = await navigator.serviceWorker.register('sw.js');

        // Wait for activation if needed
        if (!reg.active) {
          await new Promise(resolve => {
            if (reg.installing) {
              reg.installing.onstatechange = () => {
                if (reg.active) resolve();
              };
            } else if (reg.waiting) {
              resolve(); // Skip waiting for user
            }
          });
        }
        console.log("SW now active. PushManager:", reg.pushManager);
        console.log("reg object:", reg);
        console.log("reg.scope: " + reg.scope);

        const existingSub = await reg.pushManager.getSubscription();
        if (existingSub) {
          await existingSub.unsubscribe();
          console.log("Already subscribed:", existingSub);
          alert("Already subscribed");
        } else {
          console.log("Not subscribed yet.");
          alert("Not subscribed yet.");
        }
  console.log("Key length: " + urlBase64ToUint8Array(publicKey).length);

        const sub = await reg.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey: urlBase64ToUint8Array(publicKey)
        });
        console.log(sub);
        alert(sub);

        await fetch('', {
          method: 'POST',
          body: JSON.stringify(sub),
          headers: { 'Content-Type': 'application/json' }
        });

       const checkSub = await reg.pushManager.getSubscription();
        if (existingSub) {
          console.log("subscribed");
          alert("subscribed");
        } else {
          console.log("Not subscribed yet.");
          alert("Not subscribed yet.");
        }

      }catch (err) {
        console.error("Subscription failed:");
        console.error("Error name:", err.name);
        console.error("Error message:", err.message);
        console.error("Error stack:", err.stack);
        alert(`Subscribe failed: ${err.name} - ${err.message}`);
        return null;
      }
    }

    document.getElementById('subscribeBtn').onclick = () => {
      if ('serviceWorker' in navigator && 'PushManager' in window) {
        subscribe().catch(err => console.log('Error: ' + err));
      } else {
        alert('Push not supported');
      }
    };
  </script>
</body>
</html>

and this is sw.js file in the same directory:

// sw.js
self.addEventListener('install', e => self.skipWaiting());
self.addEventListener('activate', e => console.log('SW activated'));
self.addEventListener('push', e => {
  const body = e.data?.text() || 'No payload';
  e.waitUntil(self.registration.showNotification('Push', { body }));
});

some considerations:

a. i ran this script on a valid https website

b. i used valid VAPID and it works on desktop browsers including firefox and chrome

c. i granted permissions on android device so permissions not the issue!

if you could help me on this, im gratefull…

codeigniter 4 view Invalid file

Error – CodeIgniterViewExceptionsViewException
Invalid file: “/pergo/views/index.php”

SYSTEMPATHExceptionsFrameworkException.php at line 39

32 }
33
34 /**
35 * @return static
36 */
37 public static function forInvalidFile(string $path)
38 {
39 return new static(lang(‘Core.invalidFile’, [$path]));

My theme directory in root: ignore if i am wrong i am new in codings thing

Path

/themesmonoka
/themespergo
/themesregular
/themesviews
/themespergomodels
/themespergoviews
/themespergoviewsindex.php
View.php

    <?php
    
    namespace Config;
    
    use CodeIgniterConfigView as BaseView;
    
    class View extends BaseView
    {
        public array $paths = [
            // Allow views to be loaded from the themes directory
            ROOTPATH . 'themes',
            APPPATH . 'views',
        ];
    
    }

Home.php

    <?php
    
    namespace AppControllers;
    
    use AppModelsLanguageModel;
    use ConfigServices;
    
    class Home extends BaseController
    {
        public function index()
        {
            if (session()->get('uid')) {
                return redirect()->to('/new_order');
            }
    
            $homePageType = get_theme();
            if (get_option('enable_disable_homepage') && $homePageType !== 'pergo') {
                return redirect()->to('/auth/login');
            }
    
            $langModel  = new LanguageModel();
            $languages  = $langModel
                            ->where('status', 1)
                            ->findAll();
    
            // Load the index view from the active theme
            $viewPath = "$homePageType/views/index";
            return view($viewPath, [
                'lang_current' => get_lang_code_defaut(),
                'languages'    => $languages,
            ]);
        }
    }

Apple Pay for Authorize.net is not showing

I’ve completed all the necessary steps for setting up Apple Pay, including uploading the PEM certificate and verifying my domain. I’m using the WooCommerce Authorize.Net plugin (skyverge), and their instructions mention enabling Apple Pay using this filter:

 add_filter( 'wc_payment_gateway_authorize_net_cim_activate_apple_pay', '__return_true' );

By adding this filter hook in functions.php file it start showing Apple pay setting page where we can enable or disable, add prm file etc. Also i am working on safari browser. Despite following all the required steps, the Apple Pay button still isn’t appearing on the checkout page. I’ve confirmed that everything is set up correctly, but I’m not sure what I’m missing.

NGXMask – Add prefix to input

I want to add prefix : ‘https://’ to input using ngx-mask *16.4.0.
I have component using signal inputs like this:

<input
  [mask]="mask()"
  [required]="required()"
  [prefix]="prefix()"
/>

and use this in other as :

mask=""
prefix="https://"

And ofc. it doesnt work because mask is empty. If i try added S* A* it dont allow me to write . / ? etc…
I was tried to adding customPattern but its not bound with input. InstantPrefix dont exist on this version. Prefix doesnt exist in newst one…

How i will be able to write url adress with this prefix ?

LeetCode – 23. Merge k Sorted Lists algo issue

I was trying to solve this LeetCode Problem, and have been failing at it.

My Algorithm:

  • Variables with purpose:
    • head: Holds reference of head element.
    • temp: Holds reference of current pointing element and gets updated to point to next in list.
    • min: Holds minimum value of current elements
    • index: Holds index of list which has minimum value.
  • Loop while min is smaller than Number.MAX_SAFE_INTEGER
  • Start of loop, set min to max
  • Loop on every list:
    • Check if val < min
      • If so, update min with val
      • Set index to i
    • Check if node exists at that index
      • If so, set reference of node to temp.next
      • Point to node.next
      • Reset index so we do not get stale node.
  • At the end of loop, return head

Also attaching sample code:

function mergeKLists(lists: Array<ListNode | null>): ListNode | null {
    let head = null;
    let temp = null;
    let min: number;
    let index: number;
    function setVal(node): void {
        if (temp === null) temp = node;
        else temp.next = node;
        if (!head) head = temp;
        if (node) temp = temp.next;
    }
    do {
        // Used only for debug purpose
        const map = [];
        min = Number.MAX_SAFE_INTEGER;
        for (let i = 0; i< lists.length; i++) {
            map.push(lists[i] && lists[i].val)
            if (getVal(lists[i]) < min) {
                min = lists[i].val;
                index = i;
            }
        }
        if (lists[index]) {
            setVal(lists[index]);
            lists[index] = lists[index].next;
            index = null;
        }
        console.log(min, map)
    } while (min < Number.MAX_SAFE_INTEGER)
    return head;
};

function getVal(node): number {
    return node && node.val != null ? node.val : Number.MAX_SAFE_INTEGER
}

Following is the input:

lists = [[1,4,5],[1,3,4],[2,6]]

I’m seeing the output as:

1 [ 1, 1, 2 ]
1 [ 4, 1, 2 ]
2 [ 4, 3, 2 ]
3 [ 4, 3, 6 ]
4 [ 4, 4, 6 ]
1 [ 1, 4, 6 ] <— Error point
2 [ 2, 4, 6 ]
3 [ 3, 4, 6 ]

As you can see, on 6th iteration I’m again getting 1 but I’m not able to understand where that reference is coming from.

Note: I’m not looking for solution but help in correcting my algorithm. I’m sure there are better ways to solve but this is what I could think of, so would like to progress from this point.