How to create a two line ellipsis text with some suffix?

I want to create a small card like this with html & css & js, pleas see the picture in the link to see the effect I want to make:

card image sample

You can see in the picture, a card will show ellipsis when text is over two lines. Moreover, an small button is followed after the text and will not create new line.

How can I realize this card?

current code:
html:

<div class="card">
  <p>lost all your money, choose and select a rare card<button>good</button></p>
  <button>good</button>
</div>
.card{
  width: 120px;
  height: 80px;
  border: 1px solid black;
  border-radius: 8px;
  padding: 0px 4px;
  background: white;
}

.card p{
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;  
  overflow: hidden;
}

and here is the code sample in codepen: https://codepen.io/Roll-Romam/pen/VYvmvyg

In codepen sample you can see I first put button in p element, it just disappears, and when I put a button outside p element, it just creates a new line.

So maybe using javascript is the only way to realize such card? Or pure css & html can also solve this problem?

frame-ancestors CSP not being observed

I’m getting the following error: Refused to frame '<URL>' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'none'"

I’m using an Azure Static Web App. I’ve included the following in my staticwebapp.config.json:

"globalHeaders": {
    "Content-Security-Policy": "frame-ancestors 'self' https://alpha.sso.###.com https://sso.###.com;"
  }

And in the response headers I do see:

content-security-policy
frame-ancestors 'self' https://alpha.sso.###.com https://sso.###.com

So why does it think my frame-ancestors policy is none?

Replace leading minus with trailing BCE

I’m not able to use the date module in my CMS because of the historic dates (many are before the common era), I want to use numbers (this provides me with a correct sorting of the items); so when I mean to write 3600 BCE, I can only write -3600. Is there a way to replace the leading minus with a trailing text?

How to integrate Metamask Wallet with Solana DApp?

I tried all AI agents and went through a lot of documentation, but nothing helped so far.

I try to integrate Metamask wallet to my DApp similar way this app does it:
https://app.solayer.org/

I want to:

  1. Connect Metamask Wallet
  2. Request SignMessage
  3. Request SOL Transaction

How to achieve it?
AI agents points me to Metamask Snaps, but all advices reach dead end.
Did anyone manage to integrate this feature?

Custom infinite carousel animation starts to jitter and slow down after running smoothly for a bit

I am working on an an infinite carousel animation – animating the scroll of the parent element instead of the position of the elements. But after running smoothly for a bit the animation slows down and jitters a bit. I’m using anime.js.

The code is called on window.addEventListener("load", () => {...})

The image is duplicated so that I can make the infinitely repeated animation. Also, the image, for most screen sizes, is bigger than the width of the viewport.

I’be been looking at the code, which is not very complicated, but have no idea what could cause this?

const scrollContainer = document.querySelector('#clients-inner');

let scrollAnime; // store the Anime.js animation instance

function createScrollAnimation() {
  const clientImg = scrollContainer.querySelector('.client-item:first-child');
  const maxScrollLeft = scrollContainer.scrollWidth - scrollContainer.clientWidth;
  const scrollBackToSeam = scrollContainer.scrollWidth - scrollContainer.clientWidth - clientImg.clientWidth;
  const duration = maxScrollLeft * 20; // Adjust multiplier for speed (e.g., 20ms per pixel)

  scrollAnime = anime({
    targets: scrollContainer,
    scrollLeft: [{
        value: maxScrollLeft,
        duration: duration,
        easing: 'linear'
      }, // Scroll to end
    ],
    loop: false, // Loop the entire animation timeline
    autoplay: false, // Don't start automatically
    round: 1, // Round scrollLeft values to nearest pixel for smoother results
    complete: function(anim) {
      // When animation reaches the end of the original content,
      // instantly jump back to the beginning, which now looks seamless
      scrollContainer.scrollLeft = scrollBackToSeam;

      anime.remove(scrollContainer); // Remove the previous animation instance
      // Restart the animation for a continuous loop
      init();
    }
  });
}

function startScroll() {
  if (scrollAnime) {
    scrollAnime.play();
  }
}

function stopScroll() {
  if (scrollAnime) {
    scrollAnime.pause();
  }
}

function init() {
  createScrollAnimation();
  startScroll(); // Start scrolling automatically on load
}

// Optional: Pause on hover, resume on mouse leave
scrollContainer.addEventListener('mouseenter', stopScroll);
scrollContainer.addEventListener('mouseleave', startScroll);

// Recalculate animation if container size changes (e.g., window resize)
window.addEventListener('resize', () => {
  stopScroll();
  anime.remove(scrollContainer); // Remove previous animation
  init();
});

init();
<div id="clients-inner" class="inner w-full overflow-x-scroll no-scrollbar text-center">
  <!-- important next div is without spaces for smoother animations -->
  <div id="clients-wrapper"><img class="client-item p-0" src="/assets/images/homepage/clients-5.jpg"><img class="client-item p-0" src="/assets/images/homepage/clients-5.jpg"></div>
</div>

String Escape slect with options

I have items, which are rendered into a dropdown via Javascript (local script). A button to add a new line works locally on my dev web server but doesnt work on production.

I have the impression that it fail due to the things being redendered on production as options have double quotes e.g.
Screw 3″

So this has to be converted to: 3″
if my hypothesis is right.

Is there something out of the box I can use in Javascript or Ruby on Rails to do the conversion? Like <% name = item.name.gsub(""", """) %> or so?

The Script which doesnt work on production:
item.name is rendered as an option names. The name include double quotes.

<script>
    document.getElementById("IncreaseItemPositions").addEventListener("click",
        function(){
            event.preventDefault();
            var table = document.getElementById("StockTable");
            amountPositions = parseInt(table.getAttribute("positions"));
            var row = table.insertRow();
            // count is index already (starting count at 0) hence increase Positions doesnt have to be changed
            // before updating attribute & adding new row to table
            table.setAttribute("positions", amountPositions)
            // 1
            var cell = row.insertCell();
            cell.innerHTML = "<select " +
                "name="warehouse[stocks_attributes]["+amountPositions+"][item_id]" id="warehouse_stocks_attributes_"+amountPositions+"_item_id">" +
                "<option value=""\></option>"+
                <% @items.each do |item| %>
                  "<option value="<%= item.id %>"><%= item.name%></option>"+
                <% end %>
              "</select>";
            // 2
            cell = row.insertCell();
            cell.innerHTML = "0";
            //3
            cell = row.insertCell();
            cell.innerHTML = "+ <input type="text" name="warehouse[stocks_attributes]["+amountPositions+"][added_quantity]" id="warehouse_stocks_attributes_"+amountPositions+"_added_quantity">";
            console.log("Stock positions increased");
        }
    );
</script>

Text not displayed in modal despite the results

I have a function PurgeXYZs in the page’s aspx.cs file and the page is also linked to a JS file for frontend, i am trying to get results of the function “managexyz.aspx/PurgeXYZs” which are boolean properties (allDeleted and someDeleted) of ‘result’ and the text of my modal shown after execution changes accordingly to their values :

    function handlePurgeXyz(data) {
        return new Promise((resolve, reject) => {
            $.ajax({
                type: "POST",
                url: "managexyz.aspx/PurgeXYZs",
                data: JSON.stringify({
                    kmacViewModels: data,
                }),
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (data) {
                    const result = {
                        errorCode: data.d.ErrorCode,
                        message: data.d.Message,
                        allDeleted: data.d.AllDeleted,
                        someDeleted: data.d.SomeDeleted
                    };
                    resolve(result);
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    reject(new Error(textStatus));
                },
                complete: function (data) {
                    $("spn_modal_close_purge_xyz").removeClass("disabled");
                    $("spn_modal_ok_purge_xyz").removeClass("disabled");
                }
            });
        });
    }

    async function PurgeXyz(data) {
        try {
            const result = await handlePurgeXyz(data);
            let message = "";

            if (result.AllDeleted) {
                message = $("#model_content_xyz_msg_all").text();
            } else if (result.SomeDeleted) {
                message = $("#model_content_xyz_msg_some").text();
            } else {
                message = $("#model_content_xyz_msg_none").text();
            }

            $("#model_body_content_purge_xyz").text(message);
            $("#modal-dialog-purge-xyz").modal('show');

            if (result.AllDeleted || result.SomeDeleted) {
                await reloadDatatable();
            }

        } catch (error) {
            console.error(error);
            $("#model_body_content_purge_xyz").text("An error occurred while purging XYZs.");
            $("#modal-dialog-purge-xyz").modal('show');
        }
    }
    

But I can’t seem to make it work because when debugging result in the section where i check what text to show in modal remains empty… so the modal displays nothing inside. What should i change?

Logged User gets recorded in Database when instead I intend to record a financial donor in laravel and laragon

I am working on a website and i needed to record the contributions of members of that organisation in the database. And usually the logged in user can be different from the donor. However, each time I add a new contribution, it records the logged user id in the DB instead of the donor’s id. I have used dd($request->donor_user_id) in the controller to see the id being sent to the controller and it matches that of the donor. However, when I save it to the DB, I see the logged in use id instead.

Everything looks fine for me,yet it does not work. Please what could be causing this issue? See codes below.

The migration/table

public function up(): void
{
    Schema::create('church_parishioner_support_incomes', function (Blueprint $table) {
        $table->id();
        $table->integer('cause_id');
        $table->integer('donor_id');
        $table->integer('is_org_member')->default(0);
        $table->integer('organisation_id')->default(1);
        $table->integer('committee_id')->nullable();
        $table->integer('subactivity_id')->nullable();
        $table->float('amount');
        $table->float('paid');
        $table->float('balance');
        $table->string('comment')->nullable();
        $table->integer('created_by');
        $table->timestamps();
    });

The controller

public function store(Request $request, String $slug){
    $request->validate([
        'cause_id'=>['required', 'integer'],
        'donor_user_id'=>['required', 'integer'],
        'amount'=>['required', 'numeric'],
        'organisation_id'=>['required', 'integer'],
        'paid'=>['required', 'numeric'],
        'balance'=>['required', 'numeric'],
        'comment'=>['nullable'],
    ]);
    //  dd($request->donor_user_id);
    $user=User::findOrFail($request->user);
 
    $income = new ChurchParishionerSupportIncome();
    $income->donor_id=$request->donor_user_id;
    $income->cause_id=$request->cause_id;
    $income->is_org_member=1;
    $income->amount=$request->amount;
    $income->paid=$request->paid;
    $income->balance=$request->balance;
    $income->comment=$request->comment;
    $income->organisation_id=$request->organisation_id;
    $income->created_by=$user;
    $income->save();
   
    toastr('Income saved successfully', 'success');
    return redirect()->route('org.finance.orgmembers-supports.income',['slug'=>$slug, 'user'=>$user]);
}

The route

Route::post('/portal/dashboard/organisation/{slug}/finances/members/members-support-incomes/store', [OrgMembersSupportIncomeController::class, 'store'])->name('org-finance.members-supports.income.store');

The View

<section class="section"> 
<div class="mb-3">
  <a href="{{ route('org.finance.orgmembers-supports.income', [$organisation->slug, 'user'=>$user->id]) }}" class="btn bg-primary custom-txt-bcolor"><i class="fa fa-arrow-left"></i>  
    Go Back</a>
</div>

<div class="row">
  <h5>{{ $income?"Edit Members Support Income Record":"Add Members Support Incomes" }}</h5>
    <div class="col-12 col-md-12 col-lg-12">
      <div class="card card-primary">
        <div class="card-body">
              @if($income !==null)
              <form action="{{ route('org-finance.members-supports.income.update', [$organisation->slug, $income->id, 'user'=>$user->id] ) }}" method="POST" >
              @method('PUT')
              @else
            <form action="{{ route('org-finance.members-supports.income.store', [$organisation->slug, 'user'=>$user->id]) }}" method="POST" >
              @endif
              @csrf

              <div class="form-group">
                <label>Project/Cause</label>
                <select class="form-control select2" name="cause_id">
                  <option value="">Select project/cause</option>
                  @foreach ($causes as $cause )
                    <option {{ $income?$income->cause_id==$cause->id?"selected":"":"" }} value="{{ $cause->id }}">{{ $cause->name }}</option>    
                  @endforeach
                </select>
            </div>

            <div class="form-group">
              <label>Member</label>
              <select class="form-control select2" name="donor_user_id">
                <option value="">Select member</option>
                @foreach ($registeredMembers as $member )
                  <option {{ $income?$income->user_id==$member->user_id?"selected":"":"" }} value="{{ $member->user_id }}">{{ $member->user->first_name }} {{ $member->user->middle_name?$member->user->middle_name:"" }} {{ $member->user->last_name }}</option>    
                @endforeach
              </select>
          </div>
          
              <div class="form-group">
                <label>Amount donated (N)</label>
                <input name="amount" type="number" class="form-control donated_amt" value="{{ $income?$income->amount:"" }}">
              </div>
              <div class="form-group">
                  <label>Paid (N)</label>
                  <input name="paid" type="number" class="form-control paid_amt" value="{{ $income?$income->paid:"" }}">
              </div>
              <div class="form-group">
                  <label>Balance (N)</label>
                  <input name="balance" type="number" class="form-control balance_amt" value="{{ $income?$income->balance:"" }}" readonly>
                </div>
                <div class="form-group">
                  <label>Comment</label>
                  
                  <div class="form-floating">
                    <textarea name="comment" class="form-control" placeholder="Leave a comment here" id="floatingTextarea2" style="height: 100px">{!! $income?$income->comment:"" !!}</textarea>
                  </div>
                </div>
                <input name="organisation_id" type="hidden" class="form-control" value="{{$organisation->id}}" readonly>
              
              <button type="submit" class="btn btn-primary btn_submit">{{ $income?"Update":"Save" }}</button>
            </form>
          </div>
        </div>
      </div>
    </div>
  </div>

How to save PayPal details for the future payment same like card in Stripe session checkout page?

I’m using Stripe Checkout Session for the payment in my laravel project. I’ve included code like while creating checkout session:

'saved_payment_method_options' => ['payment_method_save' => 'enabled'],

I’m trying to do payment with the PayPal it’s not showing me checkbox for save for the future purchase. But when I’m using card it’s showing me checkbox for save it for future purchase. Also address is not showing if I’ve already filled one time. For that I’ve added like:

'customer_update' => [
  'name' => 'auto',
  'address' => 'auto',
],
'billing_address_collection' => 'required',

Also, I’ve question like can I use PayPal as auto payment like card:

$organization->invoicePrice(
$stripePriceId,
$quantity,
[
  'currency' => Config::get('cashier.currency'),
  'default_tax_rates' => $taxObject,
);

Where Organization model has LaravelCashierBillable trait.

Thanks…

Why is in_array not working when both the needle and haystack are very definitely exactly the same? [closed]

This one is a real head scratcher. I’ve exhausted every possible avenue with Gemini AI and even that can’t seem to solve this one.

So, I have this code which I’ve set up as a test:

$nz_array = array('NZ','nz');
$users_countrycode = do_shortcode('[userip_location type="countrycode"]');
echo("Needle = "" . $users_countrycode . ""<br />");
var_dump($nz_array);
echo("<br />Haystack = "" . $nz_array[0] . """);
if(is_string($users_countrycode)){
  echo("<br />Needle is string");
}
if(is_string($nz_array[0])){
  echo("<br />Haystack is string");
}
if($users_countrycode == $nz_array[0]){
  echo("<br />Yes, " . $users_countrycode . " is equal to " . $nz_array[0]);
}
if(in_array($users_countrycode,$nz_array)){
  echo('<br />YES, is in array!');
}

The resulting output is:

Needle = "NZ"
array(2) { [0]=> string(2) "NZ" [1]=> string(2) "nz" }
Haystack = "NZ"
Needle is string
Haystack is string

Note that both the needle and the haystack result as “NZ” and are both strings (note also that I have forced the code to display quotation marks on each side of the resulting “NZ” values to show that there are no hidden spaces, etc), and yet the lines,

if($users_countrycode == $nz_array[0])

and,

if(in_array($users_countrycode,$nz_array))

both result in no output at all! Therefore $users_countrycode does not equal $nz_array[0] and $users_countrycode is not being found in the $nz_array array.

I cannot figure out why. This always used to work perfectly, but has somehow suddenly stopped working for some obscure reason.

Any ideas?

NextJS text input is causing the whole app to freeze

so I am currently building an app using NextJS’s latest version which consists of a filter. The filter inputs are listed below:

<div className="flex mt-3">
    <div className="mr-8">
        <label for="startDate">Start Date</label>
        <br />
        <input name="startDate" id="startDate" className="border-2 rounded-lg px-3 py-2" type="date" onChange={(e) => setStartDate(e.target.value)} placeholder="Start Date" />
    </div>
    <div className="mr-8">
        <label for="endDate">End Date</label>
        <br />
        <input name="endDate" id="endDate" className="border-2 rounded-lg px-3 py-2" type="date" onChange={(e) => setEndDate(e.target.value)} placeholder="Start Date" />
    </div>
    <div className="mr-8">
        <label for="promoCode">Promo Code</label>
        <br />
        <input name="promoCode" id="promoCode" className="border-2 rounded-lg px-3 py-2" type="text" value={promoCode} onChange={handlePromoCodeChange} placeholder="Code goes here" />
    </div>
    <div className="flex items-end">
        <button type="button" onClick={filter} className="border-2 px-3 py-2 text-lg rounded-lg bg-[#52b3d6]">Search</button>
    </div>
</div>

Somehow when I tried to use my cursor to click into the input (focusing the input), the whole application went freezing and I could not do anything anymore, I have to close that specific tab and reopen a new one. Here’s my full code looks like:

import moment from "moment";
import Image from "next/image";
import { useSearchParams } from "next/navigation";
import { useRouter } from "next/router";
import { useState } from "react";

export default function Booking() {
    const searchParams = useSearchParams();
    const type = searchParams.get('type');
    const router = useRouter();
    const id = router.query.id;

    const [startDate, setStartDate] = useState(null);
    const [endDate, setEndDate] = useState(null);
    const [promoCode, setPromoCode] = useState('');

    const handlePromoCodeChange = (e) => {
        setPromoCode(e.target.value);
    };

    const filter = async () => {
        console.log("TEST startDate", startDate);
        console.log("TEST endDate", endDate);
        console.log("TEST promoCode", promoCode);
    };

    return (
        <>
            <div className="flex m-10">
                <div className="flex-none">
                    <Image src={`/test.png`} width={200} height={60} alt="logo"></Image>
                </div>
                <div className="grow my-auto text-right">
                    <h1 className="text-3xl">Test</h1>
                </div>
            </div>
            <hr />
            <div className="flex-col mx-10">
                <div className="grow my-8 text-3xl text-center">BOOK NOW</div>
                <div>
                    Enter your holiday date.
                    <div className="flex mt-3">
                        <div className="mr-8">
                            <label for="startDate">Start Date</label>
                            <br />
                            <input name="startDate" id="startDate" className="border-2 rounded-lg px-3 py-2" type="date" onChange={(e) => setStartDate(e.target.value)} placeholder="Start Date" />
                        </div>
                        <div className="mr-8">
                            <label for="endDate">End Date</label>
                            <br />
                            <input name="endDate" id="endDate" className="border-2 rounded-lg px-3 py-2" type="date" onChange={(e) => setEndDate(e.target.value)} placeholder="Start Date" />
                        </div>
                        <div className="mr-8">
                            <label for="promoCode">Promo Code</label>
                            <br />
                            <input name="promoCode" id="promoCode" className="border-2 rounded-lg px-3 py-2" type="text" value={promoCode} onChange={handlePromoCodeChange} placeholder="Code goes here" />
                        </div>
                        <div className="flex items-end">
                            <button type="button" onClick={filter} className="border-2 px-3 py-2 text-lg rounded-lg bg-[#52b3d6]">Search</button>
                        </div>
                    </div>
                </div>
            </div>
        </>
    )
}

For reference, here’s how it looks like after I focused to the text input:
Browser tab freezing
After sometime, it went all white.

I also tried textarea, hoping that I can get a workaround, but the same as well.

Can anyone tell me what’s wrong here? Thankyou!

Sending raw large table to php backend

I am trying to send outer html of the table to php backend. I am able to send little table data like 10 kb but if i try to send 10mb table then network status shows pending and does not get any status code as well. and it gets never resolve. I already maximize the post limit and all but still I am not able to send data to backend. I tried formdata method. formdata blob as well but still same issue. small table able to send to backend but for large table status showing pending and never get resolved.
frontend:

function download_table() {
    const table = document.getElementById("Dtf-table");
    if (!table) {
        alert("Table is not detected");
        return;
    }

    const html = table.outerHTML;

    fetch("factory/generate_excel1.php", {
        method: "POST",
        headers: {
            "Content-Type": "text/plain" // send raw HTML as plain text
        },
        body: html
    })
    .then(response => response.text())
    .then(fileName => {
        const a = document.createElement("a");
        a.href = `factory/${fileName.trim()}`; // path to saved file
        a.download = ""; // let browser pick the filename
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    })
    .catch(error => {
        console.error("❌ Error:", error);
    });
}

Backend:

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

use PhpOfficePhpSpreadsheetReaderHtml;
use PhpOfficePhpSpreadsheetWriterXlsx;
use PhpOfficePhpSpreadsheetCellCoordinate;

try {
    $rawHtml = file_get_contents("php://input");
    if (!$rawHtml) {
        throw new Exception("❌ No HTML content received.");
    }

    // Load HTML into Spreadsheet
    $reader = new Html();
    $spreadsheet = $reader->loadFromString($rawHtml);```

value setter for a custom select element with lazy loading

I am trying to mimic the behavior of the HTMLSelectElement value setter to work at any time, but also retain lazy loading of my custom elements. I use a base class which cache elements of the same type to prevent their template from being loaded multiple times:

const templateCache = new Map();

export class DSElement extends HTMLElement {
  constructor() {
    super();
    this._name = this.constructor._type;
    this.attachShadow({ mode: 'open' });
    this._internals = this.attachInternals();
  }

  async connectedCallback() {
    let template = templateCache.get(this._name);

    if (!template) {
      const templateUrl =
        chrome.runtime.getURL(`interface/templates/${this._name}.html`);
      const response = await fetch(templateUrl);
      const html = await response.text();

      const wrapper = document.createElement('template');
      wrapper.innerHTML = html;

      const inner = wrapper.content.getElementById(`${this._name}-template`);
      if (inner) {
        template = inner;
        templateCache.set(this._name, template);
      }

      requestAnimationFrame(() => this._after());
    }

    if (template)
      this.shadowRoot.appendChild(template.content.cloneNode(true));
  }

  async _after() {
    // Virtual method
  }
}

Then I create a DSSelect class which handles drawing stuff inside the _after method:

import { DSElement } from './ds-element.js';

class DSSelect extends DSElement {
  static _type = 'ds-select';
  
  constructor() {
    super();
    this._value = null;
    this._firstOption = null;
    this._label = null;
    this._internals.role = 'select';
  }

  async _after() {
    this._select = this.shadowRoot.getElementById('select');
    this._options = this.shadowRoot.getElementById('options');
    this._labelSpan = this.shadowRoot.getElementById('label');

    this.setInitialSelection();

    this._select.addEventListener('click', () => this.toggle());
    this.addEventListener('click', e => this.handleOptionClick(e));
  }

  setInitialSelection() {
    let firstOption;
    if (this._firstOption !== null)
      firstOption = this._firstOption;
    else
      firstOption = this.querySelector('ds-opt');
    if (firstOption)
      this.selectOption(firstOption);
  }

  selectOption(option) {
    this._value = option.getAttribute('value');
    this._label = option.textContent;
    this._labelSpan.innerText = this._label;
    this.dispatchEvent(new Event('change', {bubbles: true}));
  }

  get value() {
    return this._value;
  }

  set value(value) {
    const match = Array.from(this.querySelectorAll('ds-opt')).find(
      opt => opt.getAttribute('value') === value
    );

    if (match)
      this._firstOption = match;
  }
}

customElements.define(
  DSSelect._type, DSSelect
);

And somewhere in my code I use the setter on DOMContentLoaded event:

const reloadOptions = () => {
  const elMode = document.getElementById('mode');
  elMode.value = 'selected';
};

document.addEventListener('DOMContentLoaded', reloadOptions);

This actually works 99% of the time, until I hold down F5 to reload quickly many times. I think there is an asynchronous race happening between reloadOptions and _after function and this.querySelectorAll('ds-opt') appears empty inside the DSElement setter when _after loose.

I am not sure though what would be the correct approach here.

For completeness, the template for ds-select looks like this:

<template id="ds-select-template">
  <style>
    :host {
      display: inline-block;
      position: relative;
      user-select: none;
    }
    
    #select {
      cursor: pointer;
    }

    #options {
      display: none;
      position: absolute;
      top: 100%;
      left: 0;
      right: 0;
    }

    #options.open {
      display: block;
    }
  </style>
  <div id="select">
    <span id="label">n/a</span>
  </div>
  <div id="options">
    <slot></slot>
  </div>
</template>

And finally the ds-select element is used like:

<ds-select id="mode">
  <ds-opt value="all">
    Parse all
  </ds-opt>
  <ds-opt value="selected">
    Parse selected
  </ds-opt>
</ds-select>

html attribute does not exist for Python requests-html response object as stated in documentation

I’ve been looking for a library to help render the javascript of webpages and found requests-html. Seems to be what I was looking for, however, upon following the documentation I discovered the response object does not have an html attribute so accessing anything in that path (as follows) will not be recognised

session = HTMLSession()

r = session.get(url)

r.html.links

I am curious if this occurred prior to the lxml_html_clean module was separated from the rest of the project or should it be functioning perfectly fine regardless and my installation of the library is not correct.