hope you having great days,
i'm trying to get div for change its attribute value
but document.getElementById() is not working
i put the statement for after the div is completly load,
and even tried windows.load but nothing workout,
any suggestions?
var size_list = [[76.01, 77.81,23.99,11.09,0,11.09]
,[69.9, 71.56,20.51,14.22,9.59,14.22]
,[64.1,65.63,17.56,17.19,18.34,17.19]
,[59.22,60.63,15.15,19.69,25.64,19.69]
,[54.79,56.09,12.87,21.95,32.34,21.95]]
function size_update(src,index) {
console.log("i'm working");
let element = window.getComputedStyle(document.getElementById("thisid"),null)
element.setProperty('.height',size_list[index][0]+'%');
element.setProperty('width',size_list[index][1]+'%');
element.setProperty('top',size_list[index][2]+'%');
element.setProperty('right',size_list[index][3]+'%');
element.setProperty('bottom',size_list[index][4]+'%');
element.setProperty('left',size_list[index][5]+'%');
}
const Videoframe = ({src,index,title,before_span,span,after_span,subtitle}) =>{
try{
// do something
return(
<div>
<script>
function (){console.log("start!")};
</script>
<div className="videoframe" name = "thisid" id = "thisid" >
<div className="textgroup1">
<div className="title">{title}</div>
<div className="main">
<span>{before_span}</span>
<i className="better">{span}</i>
<span> {after_span}</span>
</div>
<div className="padding" />
<div className="subtitle">
{subtitle}
</div>
</div>
</div>
<script>
function (){console.log("ended!")};
</script>
</div>
);}
finally{
size_update(src,index);
}
}
export default Videoframe;
export { size_list }
tried googling and window.load
window.getComputedStyle() returns the style of the object, but you need the DOM-Element.
To get an element once the document is loaded you need to use the window load event by doing either
window.addEventListener("load", () => {
let element = document.getElementById("thisID");
});
or
window.onload = () => {
let element = document.getElementById("thisID");
};
In both cases, you supply a function to be executed once the document is loaded. Note that the code inside the eventhandler is executed only when the site is loaded, so after the code which is written after this code snippet. If you want to access the element, you'll need to write the logic for the element inside the function.
Related
Is it possible to execute a <Script/> every time the props of a react/nextjs component change?
I am converting markdown files to html using marked and, before rendering the html, I would like to have a [copy] button on each <pre> block (those are the code blocks). I have a <script/> that iterates through the <pre> blocks of the DOM document.querySelectorAll("pre") and injects the button needed. If the html changes though at a later stage, then I have found no way to re-run the script to add the copy buttons again.
I have the impression that this is not a very react/nextjs way of doing this, so any hints would be appreciated.
The Script to add the copy buttons. I have added this as the last tag of my <body>:
<Script id="copy-button">
{`
let blocks = document.querySelectorAll("pre");
blocks.forEach((block) => {
if (navigator.clipboard) {
let button = document.createElement("img");
button.src = "/images/ic_copy.svg"
button.title = "Copy"
button.id = "copy"
button.addEventListener("click", copyCode);
block.appendChild(button);
}
});
async function copyCode(event) {
const button = event.srcElement;
const pre = button.parentElement;
let code = pre.querySelector("code");
let text = code.innerText;
await navigator.clipboard.writeText(text);
button.src = "/images/ic_done.svg"
setTimeout(()=> {
button.src = "/images/ic_copy.svg"
},1000)
}
`}
</Script>
the React component. Not much to say here. The content is coming from the backend. Not sure what would be the 'React' way to do this without the script.
export default function Contents({ content }) {
return (
<div className='pl-2 pr-2 m-auto w-full lg:w-2/3 mb-40 overflow-auto break-words'>
<div className="contents" dangerouslySetInnerHTML={{ __html: content }} />
</div>
)
}
You should absolutely not do this and instead incorporate this logic into your react app, but if you must you can leverage custom window events to make logic from your html script tags happen from react.
Here is an example script:
<script>
function addEvent() {
function runLogic() {
console.log("Stuff done from react");
}
window.addEventListener("runscript", runLogic);
}
addEvent();
</script>
And calling it form react like this:
export default function App() {
const handleClick = () => {
window.dispatchEvent(new Event("runscript"));
};
return (
<div className="App" onClick={handleClick}>
<h1>Hello</h1>
</div>
);
}
I am generating some div's and appending to the DOM with this function
//Run forEach method on newObj(cats from local storage) to populate and append template to the DOM
function getTheCats() {
//Limiting the results to 3. Probably better way to do this.
newObj.slice(0, 3).forEach(cat => {
const catEl = document.createElement('div')
catEl.classList.add('cat-detail')
catEl.innerHTML = `
<div class="img-id-container" id="pointer-control" onclick="getCatDeets()">
<img class='cat-image' src='${cat.thumbnail_url}' alt="Cat Pic"/>
<h3 class="id-left">Cat ${cat.id}</h3>
</div>
<p class="birthday-left">${cat.birthdate}</p>
`
mainLeft.appendChild(catEl)
})
}
getTheCats()
I am trying to log to console, some of the innerHTML when I click on one of the results.
I always get 'undefined' as a result. I know I am missing something, but I can't seem to figure out what. Any help would be greatly appreciated.
function myFunction(event) {
const clickedCat = event.target.nodeName;
console.log(clickedCat);
const details = clickedCat.innerHTML
console.log(details)
}
From David784 in the comments,
I unnecessarily added .nodeName to event.target
I replaced it with .innerHTML and I am able to retrieve the data I need.
function myFunction(event) {
const clickedCat = event.target.innerHTML;
console.log(clickedCat);
const details = clickedCat.innerHTML
console.log(details)
}
I have an app that simply hides content Hidden.svelte:
<script>
let shown = false;
function show() {
shown = true;
}
</script>
<svelte:options accessors={true}/>
{#if shown}
<slot/>
{/if}
Parent App.svelte:
<script>
import Hidden from 'Hidden';
let child;
</script>
<Hidden bind:this={child}>
Content
</Hidden>
<button on:click={() => child.shown = true}>Show</button>
So, child's shown can be easily set due to <svelte:options accessors={true}/> in parent
But, I want to use method show() since it can not only set shown value, but also perform some magic
Thx to Chrome's DevTools, I found that all components have an Array with props and methods, that could be accessed via some .$$.ctx, so Hidden's show() method can be called like this:
<button on:click={() => child.$$.ctx[2]()}>Show</button>
But) You know) Is there are legal way to do it?
Hidden.svelte
<script>
let shown = false;
export function show() {
shown = true;
}
</script>
{#if shown}
<slot/>
{/if}
App.svelte
<script>
import Hidden from './Hidden.svelte';
let child;
</script>
<Hidden bind:this={child}>
Content
</Hidden>
<button on:click={() => child.show()}>Show</button>
The call to child.show() can actually be simplified, but I thought this could make it harder to figure out what's going on in the example. You can do just:
<button on:click={child.show}>Show</button>
I've got two problems here. The first is that I can't get the star rendered properly. I can do it if I change the value in the data() function but if I want to do it in a function callback way, it doesn't work (see comments below). What's going wrong here? Does it have something to do with Vue's lifecycle?
The second one is that I want to submit the star-rate and the content of the textarea and when I refresh the page, the content should be rendered on the page and replace the <textarea></textarea> what can I do?
I want to make a JSFiddle here but I don't know how to make it in Vue's single-file component, really appreciate your help.
<div class="order-comment">
<ul class="list-wrap">
<li>
<span class="comment-label">rateA</span>
<star-rating :data="dimensionA"></star-rating>
</li>
</ul>
<div>
<h4 class="title">comment</h4>
<textarea class="content" v-model="content">
</textarea>
</div>
<mt-button type="primary" class="mt-button">submit</mt-button>
</div>
</template>
<script>
import starRating from 'components/starRating'
import dataService from 'services/dataService'
export default {
data () {
return {
dimensionA: '' //if I changed the value here the star rendered just fine.
}
},
components: {
starRating
},
methods: {
getComment (id) {
return dataService.getOrderCommentList(id).then(data => {
this.dimensionA = 1
})
}
},
created () {
this.getComment(1) // not working
}
}
</script>
What it seems is scope of this is not correct in your getComment method, you need changes like following:
methods: {
getComment (id) {
var self = this;
dataService.getOrderCommentList(id).then(data => {
self.dimensionA = 1
})
}
},
As you want to replace the <textarea> and render the content if present, you can use v-if for this, if content if available- show content else show <textarea>
<div>
<h4 class="title">comment</h4>
<span v-if="content> {{content}} </span>
<textarea v-else class="content" v-model="content">
</textarea>
</div>
See working fiddle here.
one more problem I have observed in your code is you are using dynamic props, but you have assigned the prop initially to the data variable value in star-rating component, but you are not checking future changes in the prop. One way to solve this, assuming you have some other usage of value variable is putting following watch:
watch:{
data: function(newVal){
this.value = newVal
}
}
see updated fiddle.
I'm working on a simple application which is single page based (due to project restrictions) and has dynamic content. I understand the dynamic content alright but what I don't understand is how to set-up a script that changes the html of a div when the hash value in the URL changes.
I need a JavaScript script to work as such:
Url: http://foo.com/foo.html div contents: <h1>Hello World</h1>
Url: http://foo.com/foo.html#foo div contents: <h1>Foo</h1>
How would this work?
Please help! Thanks.
You can listen to the hashchange event:
$(window).on('hashchange',function(){
$('h1').text(location.hash.slice(1));
});
personally, I'd use sammy which gives you the flexibility to template the hashtag (add placeholders and be able to read them back). e.g.
<script src="/path/to/jquery.js"></script>
<script src="/path/to/sammy.js"></script>
<script>
$(function(){
// Use sammy to detect hash changes
$.sammy(function(){
// bind to #:page where :page can be some value
// we're expecting and can be retrieved with this.params
this.get('#:page',function(){
// load some page using ajax in to an simple container
$('#container').load('/partial/'+this.params['page']+'.html');
});
}).run();
});
</script>
Load foo.html
Load bar.html
An example can be found here: http://jsfiddle.net/KZknm/1/
Suppose we have list of items, each items has a hash tag as #id
const markup = `
<li>
<a class="results__link" href="#${recipe.recipe_id}">
<figure class="results__fig">
<img src="${recipe.image_url}" alt="${limitRecipeTitle(recipe.title)}">
</figure>
<div class="results__data">
<h4 class="results__name">${recipe.title}</h4>
<p class="results__author">${recipe.publisher}</p>
</div>
</a>
</li>
`;
Now when a user click on any of those list item or reload (http://localhost:8080/#47746) an item with hash tag, hash event will be fired. To recive the fired hash event we must register hash event listener in our app.js
//jquery:
['hashchange', 'load'].forEach(event => $(window).on(event, controlRecipe));
//js:
['hashchange', 'load'].forEach(event => window.addEventListener(event, controlRecipe));
catch the id in your controlRecipe function
const controlRecipe = async ()=>{
//jq
const id = $(window)..location.hash.replace('#','');
//js
const id = window.location.hash.replace('#','');
if(id){
//console.log(id);
state.recipe = new Recipe(id);
try {
await state.recipe.getRecipe();
state.recipe.calcTime();
state.recipe.calcServings();
console.log(state.recipe);
} catch (error) {
alert(error);
}
}
}