How to use text between the tags in a svelte component? - components

Let's say I have two components:
Bold1.svelte:
<script>
external let t="";
</script>
<b>{t}</b}
Usage:
<Bold1 t="my text 1" />
Works like expected.
Bold2.svelte:
<script>
</script>
<b>???</b>
Usage:
<Bold2>
my text 2
</Bold2>
What do I have to write instead of ??? to get a bold my text 2? I have tried <b>{this}</b>, but without success.

Get the slot content.
App.svelte:
<script>
import Child from './Child.svelte';
</script>
<Child>Hi</Child>
Child.svelte
<script>
import { onMount } from 'svelte';
let thisObj;
let text = '';
onMount(() => {
text = thisObj.textContent;
});
</script>
<div bind:this={thisObj}>
<slot />
</div>
<h3>
Slot content-1: {text}
</h3>

Are you trying to pass HTML and have it render as HTML?
If var t has HTML, you can render it like this:
{#html t}
https://svelte.dev/docs
Just watch out for XSS risk.

Related

How to scrape from 2 divs that are on the same level with Cheerio

I'm trying to web scrape content from 2 different divs that are on the same level. I'm using NodeJS, Axios, Cheerio and Express.
Basically, I'm trying to collect an image and the info related to it, but they are placed of different divs that are on the same level. Using the "main" doesn't seem to work in my case.
<div class="main">
<div class="one">
// image
</div>
<div class="two">
// info
</div>
</div>
Below is my code to get the data from a website:
var leafletList = $('.store-flyer__info', html).each(function() {
let leaflet = {
title: $(this).find('h3').text(),
image: $(this).find('source').attr('srcset'),
link: $(this).find('a').attr('href'),
validDate: $(this).find('small').text().slice(3,-1)
}
leaflets.push(leaflet)
})
Below is the website's HTML:
The way my code is right now, it's obviously getting only the title, link and validDate. But anyone knows how can I get the the srcset from the other div? I've also tried the following method, but it doesn't work:
var leafletList = $('.store-flyers', html).each(function() {
let leaflet = {
title: $(this).find('.store-flyer__info h3').text(),
image: $(this).find('.store-flyer__front source').attr('srcset'),
link: $(this).find('.store-flyer__info a').attr('href'),
validDate: $(this).find('.store-flyer__info small').text().slice(3,-1)
}
leaflets.push(leaflet)
})
There are many ways to get the result based on the HTML snippet you show, with the caveat that the developer tools can be misleading. It shows elements created after page load with JS, which you won't have if you're only requesting the raw page HTML.
With that in mind, here are a few options:
const cheerio = require("cheerio"); // ^1.0.0-rc.12
const html = `
<div class="store-flyer">
<picture>
<source srcset="foo.jpeg" type="image/webp">
<source srcset="bar.jpeg" type="image/jpeg">
</picture>
</div>
<div class="store-flyer">
<picture>
<source srcset="quux.jpeg" type="image/webp">
<source srcset="garply.jpeg" type="image/jpeg">
</picture>
</div>
`;
const $ = cheerio.load(html);
const result = [...$(".store-flyer")].map(e => ({
// select using `.first()` and `.last()` Cheerio methods:
firstImage: $(e).find("source").first().attr("srcset"),
secondImage: $(e).find("source").last().attr("srcset"),
// select using CSS attribute selectors:
firstImageByType: $(e).find('source[type="image/webp"]').attr("srcset"),
secondImageByType: $(e).find('source[type="image/jpeg"]').attr("srcset"),
// select as an array of all <source> elements:
allImages: [...$(e).find("source")].map(e => $(e).attr("srcset")),
}));
console.log(result);
Output:
[
{
firstImage: 'foo.jpeg',
secondImage: 'bar.jpeg',
firstImageByType: 'foo.jpeg',
secondImageByType: 'bar.jpeg',
allImages: [ 'foo.jpeg', 'bar.jpeg' ]
},
{
firstImage: 'quux.jpeg',
secondImage: 'garply.jpeg',
firstImageByType: 'quux.jpeg',
secondImageByType: 'garply.jpeg',
allImages: [ 'quux.jpeg', 'garply.jpeg' ]
}
]
Prepending .store-flyer__front to your source selectors might be a good idea if you need to disambiguate.
With cheerio, you can access node properties such as:
parentNode
previousSibling
nextSibling
nodeValue
firstChild
childNodes
lastChild
<div class="main">
<div class="one">
// image
</div>
<div class="two">
// info
</div>
</div>
.main.firstChild is .one
.one.nextSibling is .two
.main.lastChild is .two
.two.previousSibling is .one

MathJax is rendering twice

I have a MathJax demo that can be viewed at Online Demo.
In this demo, I have some Tex markup within a div that gets rendered perfectly by MathJax.
But, if I programatically add some Tex markup to the above div by clicking Add Math Markup button followed by clicking Rerender Math Markup button, then it results in repeated rendering of previously rendered Math markup. This can be seen in following video: Math being rendered repeatedly
All I am doing when Rerender Math Markup button is clicked is calling the following method MathJax.Hub.Typset(divElement). The divElement is the div to which Tex markup was added programatically.
Demo code for my situation
<script>
function reRenderMath() {
var div = document.getElementById("mathMarkup");
//render Math for newly added Tex markup
MathJax.Hub.Typeset(div);
}
function addMath() {
var div = document.getElementById("mathMarkup");
div.innerHTML = div.innerHTML + "$$\sin^{-1}.6$$";
document.getElementById("btnRenderMath").disabled = false;
}
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});
</script>
<script type="text/javascript"
src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<button type="button" onclick="addMath();return false;" id="btnAddMath" >Add Math Markup</button>
<button type="button" onclick="reRenderMath();return false;" id="btnRenderMath" disabled>Rerender Math Markup</button>
<div id="mathMarkup">
$$x^2 = x +2$$
</div>
Screen shot of repeated rendering
#Sunil thanks for the answer
Summarizing:
Required script:
var MathJaxUtils = (function () {
let obj = {};
let scripts = null;
obj.render = function (element) {
scripts = new Array();
$(element).find("script[id^='MathJax-Element']").each(function () {
scripts.push({
displayElement: $(this).prev("div")[0],
scriptElement: this
});
});
//remove all html within MathJax script tags so it doesn't get typset again when Typeset method is called
$(element).find("script[id^='MathJax-Element']").remove();
//render Math using original MathJax API and in callback re-insert the MathJax script elements in their original positions
MathJax.Hub.Queue(["Typeset", MathJax.Hub, element, typeSetDone]);
};
//callback for Typeset method
function typeSetDone() {
for (var i = 0; i < scripts.length; i++) {
$(scripts[i].displayElement).after(scripts[i].scriptElement);
}
//reset scripts variable
scripts = [];
};
return obj;
}());
Basic use:
let elem = document.getElementById("mathContainer");
MathJaxUtils.render(elem);
Demo:
math-jax-test

How to render the HTML into react component

I want to render the pure HTML coming from some external source into react component. I saw few solutions where people are talking about some conversion tools (HTML to JSX) but I want to handle everything in my component so while mounting it will get the HTML response and that needs to render.
You can use dangerouslySetInnerHTML for this:
function createMarkup() { return {__html: 'First ยท Second'}; };
<div dangerouslySetInnerHTML={createMarkup()} />
But as the method name suggests: you should be very sure of what you are doing there and the security implications it has.
This shouldn't be difficult to do . Assign your HTML to a div and then render it using {variable name} JSX allows you to do this and with ES6 integration you can also use class instead of className.
var Hello = React.createClass({
render: function() {
var htmlDiv = <div>How are you</div>
return <div>Hello {this.props.name}
{htmlDiv}
</div>;
}
});
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>

ejs include on click

I'm trying to create a dynamically included in an ejs page (using <%- include('partials/content') %>) on my node.js project.
Is there a way I can create a variable for the to-be-included page and change it on a button click?
Let's assume your partials/content file includes content like:
<h1>Lorem ipsum dolor sit amet</h1>
A file named partials/content2:
<h1>consectetur adipiscing elit<h1>
Your main template file would wrap the partials content by a <div> with the id result and include a script file where you select this <div> by using var $result = $('#result'); so you have it in a variable. Then you can register a click handler on your button. On click you request the wished template file and replace the content.
Main template:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
</head>
<body>
<div id="result">
<%- include partials/content.ejs %>
</div>
<button id="change">change</button>
<script>
var $result = $('#result');
$('#change').click(function() {
$result.load('/content2');
});
</script>
</body>
</html>
Then you need a controller on the backend like:
app.get('/content2', function (req, res) {
res.render('partials/content2');
});

Change polymer attributes externally

I see a lot of questions regarding on how to listen for changes in attributes. But none on how to actually change them.
Even in debug, I can't find the attributes in the object tree. How do I achieve this? is there a more polymeric way of doing the following ?
<polymer-element name="my-element" attributes="owner">
<template>
<p id="el">{{owner}}</p>
</template>
<script>
Polymer({
owner: "Miguel",
});
</script>
</polymer-element>
<my-element id="el1" owner="blabla"></my-element>
<script>
$(document).ready(function(){
$("el1").owner = "Mary"
})
</script>
It prints blablab, but doesn't change it to Mary
In 0.5, you need to wait for polymer-ready. See docs here.
<head>
<link rel="import" href="path/to/x-foo.html">
</head>
<body>
<x-foo></x-foo>
<script>
window.addEventListener('polymer-ready', function(e) {
var xFoo = document.querySelector('x-foo');
xFoo.barProperty = 'baz';
});
</script>
</body>
Ideally, your app would be one element like <my-app></my-app> so that you'd have a binding for the owner attribute like so:
<my-element owner="{{owner}}"></my-element>
And my-element would reside in another Polymer element in which you can set the owner attribute like so:
// Parent Polymer element
Polymer({
_someFunctionYouCall: function() {
this.owner = 'Mary';
}
});

Resources