How do I make SVG components? - javascript

I try to make a set of self contained SVG components which include CSS and Javascript, that can be added to a web page via templating. The idea is to be able to add self contained components without changing the base web page. A component could be something like like:
<div id="component-1" ...>
<svg>
<css>
.. css for styling component
</css>
<line ...>
<text ....>
... component svg
<script>
.... functions that manipulate the component
</script>
</svg>
</div>
The same component may be added multiple times. Is there a standard way to do this?

Related

How to add preventDefault on element, that was rendered by UI lib (antd)?

I'm using Select with a RangePicker inside (React app). The problem is that RP rendering dropdown calendar in body tag and when I press on it Select is closing. As I understand it will be fixed if I put click event prevent defaut. Is there a way to do it?
<body>
<root>
<div classname=app>
My select is a n-th (may be like 7-10) child of this tag
</div>
</root>
<div>
<dropdown /> <---- that I need to add prevent default
</div>
</body>
There is a dropdownRender property in the Select component. With it you can customize the render of the component (parent of render, styles, properties etc).

Is it possible to emulate v-model input behaviour on a paragraph tag?

Solution:
Thanks to #Jeronimas I figured out how to use dynamic components in vue. Basically you create a child component that switches between <p>and <input> tags, depending on props. You have to use <component> element for this, because it's an inherent vue component to manage dynamic components.
child:
<template>
<input v-if="input" type="text" value="hello world">
<p v-else>hello world</p>
</template>
<script setup>
const props = defineProps({
input: Boolean
})
//emit input when form is submitted...
</script>
parent:
<template>
<component :is="p" :input="true"/>
</template>
<script setup>
import p from './p.vue'
</script>
Vue is awesome <3.
Original Question:
Is it possible to input text into <p> tags, so that it will be stored in a database? I want to build a "live" CMS, similar to wordpress/webflow and using formatted <input> fields instead of <p>/<h> elements would make the html messy because, basically you would have to create two identical sites, one with normal text tags and the editable one with input fields, that look like normal text tags.
I was wondering if there is a way to manipulate reactive objects like ref to make it possible?
Alternatively you could create a site completely without normal text tags and instead use input field placeholders but that might mess up SEO.
Like in the comment above using :is could work when switching between the states.
<component :is="tag">
tag value could be dynamic and depending on the tag value the component would change its state.
I would suggest using div with v-html that supports any markup when in live mode and when user is in editing mode display a rich text field. For rich text editing i would suggest to look at https://tiptap.dev/
you can bind the input value and the tiptap would create any html tags you need <p/>, <li/>, <h1/>

Reusing piece of HTML + knockout

Basing on nice tutorial I've created an overlay with Google-style spinner. HTML in my case is minimum and looks like following:
<div class="spinner-wrapper" data-bind="visible: spinnerVisible">
<svg class="spinner" viewBox="25 25 50 50">
<circle cx="50" cy="50" r="20" fill="none" stroke-width="4" stroke-miterlimit="10" />
</svg>
</div>
Note the data-bind="visible: spinnerVisible".
I'd like to reuse this among different places in my application to avoid DRY problems. What approach may I take? Keep in mind, that visibility of the spinner wrapper will be controlled by different viewmodels (although I may guarantee each one to have spinnerVisible property).
I'd use a (template-only) knockout component with the new web component-like syntax.
Two steps to get it to work:
1. Register a component and define its template paramaters:
Here, you define your template and the parameters it needs to render. In your case, only a named observable that controls the visible binding.
ko.components.register('spinner', {
template:
'<div data-bind="visible: spinnerVisible">A spinner<hr/></div>'
});
2. Use it with the correct parameters in your HTML
Now, whatever your viewmodel's spinner controlling property may be, you can reuse the same component to render it. For example:
<spinner params="spinnerVisible: loading"></spinner>
<spinner params="spinnerVisible: pendingRequests().length > 0"></spinner>
Note that if you use the regular component binding, you'll lose some of the clean syntax.
Here's an example showing the code above in action:
ko.components.register('spinner', {
template:
'<div data-bind="visible: visible">A spinner<hr/></div>'
});
ko.applyBindings({
someProp: ko.observable(true)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<p>Regular syntax</p>
<div data-bind="component: {
name: 'spinner',
params: { visible: someProp }
}"></div>
<p>Web component</p>
<spinner params='visible: someProp'></spinner>
<button data-bind="click: someProp.bind(null, !someProp())">toggle</button>

Polymer 1.0+, can't define template in light dom for use by component

In Polymer 1.0+, how do you pass in a template from the light dom to be used in the dom-module? I'd like the template in the light dom to have bind variables, then the custom element use that template to display its data.
Here is an example of how it would be used by the component user:
<weather-forecast days="5" as="day">
<template id="forecast-template">
<img src="{{day.weatherpic}}">
<div>{{day.dayofweek}}</div>
<div>{{day.wordy}}</div>
<div>{{day.highlowtemp}}</div>
</template>
</weather-forecast>
This weather-forecast component would contain an iron-list in the dom-module and ideally, the component would reference the "forecast-template" inside the iron-list that would bind the variables to the element. Ultimately, it would generate a 5-day forecast using that template. My issue is that I haven't seen an example of bind-passing variable based templates into a Polymer 1.0 custom element. I would think this or something similar would be fairly commonplace.
The following is an example of how I would like to see it work on the client side, but no luck yet. Although the template is successfully references, it only displays once, while other fields actually do show in the loop.
<dom-module id="weather-forecast">
<template is="dom-bind">
<iron-list items="[[days]]" as="day">
<content selector='#forecast-template'"></content>
</iron-list>
</template>
</dom-module>
Any input is appreciated. Thanks!
You cannot use dom-bind inside another polymer element.
Your first element should just be dom-bind
<template is="dom-bind">
<iron-list items="[[days]]" as="day">
<weather-forecast day=[[day]]></weather-forecast>
</iron-list>
</template>
Your second element should be weather-forecast
<dom-module id="weather-forecast">
<template>
<style></style>
<img src="{{day.weatherpic}}">
<div>{{day.dayofweek}}</div>
<div>{{day.wordy}}</div>
<div>{{day.highlowtemp}}</div>
</template>
<script>
Polymer({
is: "weather-forecast",
properties: {
day: {
type: Object
}
}
});
</script>
</dom-module>
If this does not work, try wrapping the weather-forecast tag inside a template tag inside iron-list.
You can use the Templatizer. You can look at my blog for some example (there's also a Plunker link).
Unfortunately there seems to be some bug or limitation, which breaks two way binding:
Add a "dynamic" element with data-binding to my polymer-element
Polymer: Updating Templatized template when parent changes
Two way data binding with Polymer.Templatizer

Knockout SPA: Different Layouts(Master pages)

I'm building SPA application with knockout.js .
Basically what i do is bind as current page a ko component depending on what is route.
It looks something like
<div id="currentPage" data-bind="component: { name: currentRoute.page,
attr: currentRoute }>
</div>
This is for the current page and the whole picture whit the layout looks like:
<html>
<head></head>
<body>
<div data-bind="component: {name: "nav"}></div>
<div data-bind="component: {name: "aside"}></div>
<div id="currentPage" data-bind="component: { name: currentRoute.page,
attr: currentRoute}">
</div>
</body
</html>
The problem is that i dont have one layout.. the other one looks like this (pseudo used)
<html>
<body>
<wrapper>
<currentPage>
</wrapper>
</body
</html>
So basically the first layout is not direct parent of the currentPage module but the second is..
The variants for dynamic layout changing that i can think of are
Specify the layout components in each page.. But i dont think it is good idea cause i will be writing the same code over and over and will not be able to persist the state in the layout component because of when i change the next page the layout will be recreated( not fully but enough to loose the state )
The layout is separate from the currentPage component so only the currentComponent binding will be changed.. this is perfect for persisting state in layout but not good when i have variant where i want different layout for example which is wrapper around the componentBinding..
I'll be very happy if some one shares fresh ideas how to solve such problems.
In knockout if any part of view is to be dynamically changed you got to have bindings attached to the view. You say that the outer layout of the page is dependent on the inner page being displayed, so logically I consider it part of that page view definition. That is why I would not look for some special way to handle this case.
If I am not missing something, the reasonable thing to do in this case is to just include layout in each page. You could then handle repetitive code by using "traditional" approach using knockout templates (especially Note 5 on dynamic templates from http://knockoutjs.com/documentation/template-binding.html) and code extraction.
Completely other approach you might want to take is to put all layouts in master page and then control them by using bindings like "if" and "visible".

Categories