How clone image in pure js - javascript

I wrote JS to clone image and attached this action to button.
It works but I'm not sure that this better way to do it.
My questions:
is it correct to use querySelector to return elements, or is it better to add additional classes or id for buttons and pictures?
use cloneNode is optimal or better use other ways in this case?
(function() {
'use strict';
document.querySelector('button[action="button"]').addEventListener('click', function() {
let image = document.querySelector('img[alt="Dog"]');
let cln = image.cloneNode(true);
document.getElementById('image-section').appendChild(cln);
});
})();
<body>
<div id="overview">
<section class="section--center">
<button action="button">Yeah, I want more dogs!</button>
</section>
<section class="section--center" id='image-section'>
<img src="https://www.purina.com/sites/g/files/auxxlc196/files/styles/kraken_generic_max_width_480/public/HOUND_Beagle-%2813inch%29.jpg?itok=lN915WHC" alt="Dog" style="width: 150px">
</section>
</div>
</body>

Another option is updating innerHTML, but it's not better.
An approach should solve a task, so it depends on the task.
(function() {
'use strict';
document.querySelector('button[action="button"]').addEventListener('click', function() {
document.getElementById('image-section').innerHTML +=
document.querySelector('img[alt="Dog"]').outerHTML;
});
})();
<body>
<div id="overview">
<section class="section--center">
<button action="button">Yeah, I want more dogs!</button>
</section>
<section class="section--center" id='image-section'>
<img src="https://www.purina.com/sites/g/files/auxxlc196/files/styles/kraken_generic_max_width_480/public/HOUND_Beagle-%2813inch%29.jpg?itok=lN915WHC" alt="Dog" style="width: 150px">
</section>
</div>
</body>

Related

JavaScript code not working with multiple HTML elements

I've build myself a sign input on my website inside a modal popup. The problem is that I can have an unknown amount of modals generated in a foreach within PHP. Because of this my JavaScript code don't works anymore. Do you have any idea how I can improve my function to make it workable for a undefined amount of signature modals?
var signaturePad;
jQuery(document).ready(function () {
jQuery(document).on('opened', '#sign-modal', function () {
var signaturePadCanvas = document.querySelector('.signature-pad-canvas');
var parentWidth = jQuery(signaturePadCanvas).parent().outerWidth();
signaturePadCanvas.setAttribute("width", parentWidth);
signaturePad = new SignaturePad(signaturePadCanvas);
jQuery('#clear-signature').click(function () {
if (signaturePad) {
signaturePad.clear();
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/signature_pad#3.0.0-beta.3/dist/signature_pad.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/remodal#1.1.1/dist/remodal.min.js"></script>
<div id="sign-modal" class="remodal remodal remodal-is-initialized remodal-is-opened" data-remodal-id="sign-nda-modal-1234567889">
<button data-remodal-action="close" class="remodal-close"></button>
<h1>Hello</h1>
<p>I am a random text</p>
<div class="signature-pad-canvas-container">
<div class="signature-pad-canvas-wrapper">
<canvas class="signature-pad-canvas"></canvas>
</div>
<div class="clear-signature-wrapper">
<span id="clear-signature">Delete</span>
</div>
</div>
<br>
<div class="remodal-buttons">
<button data-remodal-action="cancel">Cancel</button>
<button onclick="sign('123abc', '456cdf')">Sign</button>
</div>
</div>
<div id="sign-modal" class="remodal remodal remodal-is-initialized remodal-is-opened" data-remodal-id="sign-nda-modal-9876543">
<button data-remodal-action="close" class="remodal-close"></button>
<h1>Hello</h1>
<p>I am a random text</p>
<div class="signature-pad-canvas-container">
<div class="signature-pad-canvas-wrapper">
<canvas class="signature-pad-canvas"></canvas>
</div>
<div class="clear-signature-wrapper">
<span id="clear-signature">Delete</span>
</div>
</div>
<br>
<div class="remodal-buttons">
<button data-remodal-action="cancel">Cancel</button>
<button onclick="sign('764647gc', 'iuhiz78')">Sign</button>
</div>
</div>
......
The reason why your modals have stopped working is because each modal you create is created with the same id.
This means that when you access the element with DOM, only the first element would be returned. Using a class is not the best idea as you lose the ability to target specific elements without looping.
The best solution in my opinion is to dynamically generate the id as you create your modals. This means you could have something like sign-modal-1, sign-modal-2 etc for each modal you create.
Then, in JQuery, you target elements with ID's that get opened, that begin with sign-modal, i.e. using the JQuery attribute selector.
JQuery Attribute Selector:
https://api.jquery.com/attribute-starts-with-selector/

two division put the details in inner div using jquery

i have 2 divisoin
<div id="details">
<div id="feature">
</div>
</div>
I need to put the content using $("#details").html(content); (it is working correctly) like that way i need to put the content inside feature div i am using following way:
$("#details #feature").html(content);
but it is not working..how to solve?
When you use $("#details").html(content); you override the content of the div. So you're inner div with the id feature gets removed. Maybe you use $("#details").prepend(content); or you add another div for the main content and replace that content.
Look here is an example:
https://jsfiddle.net/morrisjdev/s9u7rfcu/
ID is a unique attribute so you can directly use id like below.
$(function() {
var content = "Some text here";
$('#feature').html(content);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="details">
<div id="feature">
</div>
</div>
OR
$(function() {
var content = "Some text here";
$('#details').find('#feature').html(content);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="details">
<div id="feature">
</div>
</div>
$(document).ready(function(){
var htmldetail ="Hello! I am Here";
var details = $("#details").html(htmldetail);
$("#userfeature").html(details);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div id="details">
<div id="userfeature">
</div>
</div>
The second is #feature and not #userfeature. And also add the jQuery Library as well. You can replace test with content variable.
$("#feature").html("test");
<div id="details">
<div id="feature">
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
And also remember Id is unique and hence no need to mention its parent.
Run the following snippet and you can get the output.
Simple way..Go Through this
HTML
<div id="details">
<div id="feature">
</div>
</div>
JQUERY
$(document).ready(function()
{
var content="contain sample data";
// $("#details").html(content); if you wrote like this,
this will replace all content, so the inner div will be replaced
$("#details").append(content); // outer div
$("#feature").html(content);
});
Or you can use css-like selector method:
$(document).ready(function() {
$('#details > #feature').html('Hello <strong>World!!!</strong>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="details">
<div id="feature">
</div>
</div>
I have created a plunk for it and it is working.
Try including the action inside
$( document ).ready(function() {
console.log( "ready!" );
var content = 'Hey there';
$("#details #feature").html(content);
});
Plunk :- http://plnkr.co/edit/63GsIoGmprnKs7oe77cF?p=preview

Performance wise and fastest way to get all element with Id inside a container element

I am trying to refactor and make a performance wise code.
The idea of the code is to update the id or value of all element with id or value that needs to be updated that happens when an element has been removed / deleted
So what I am trying to do is get all element with Id or value inside a container element (which is possible to be nested in 2 to 4).
At the moment, I am using jQuery to this task. I added a class on every element that has Id and use jQuery .find() to get all of this element using the class I've assign to them .. which is I really hate about my code and wanted to change as well if there's another best way to do it.
So is there a fastest way and performance wise at the same time to do this task?
$("button").on("click", function(){
$($(this).val()).remove();
updateParagraph();
});
function updateParagraph() {
$(".paragraphs").each(function(index, data){
var dataId = data.id.split("-");
var idIndex = dataId[dataId.length-1];
var index = index + 1;
if (index != idIndex) {
dataId.splice(-1, 1);
dataId.push(index);
dataId = dataId.join("-");
$(this).attr("id", dataId);
setChildElementsId($(this), index)
}
});
}
function setChildElementsId(parent, inx) {
$(parent).find(".id-holder").each(function(index, data){
if (data.id) {
var dataId = data.id.split("-");
dataId.splice(-1, 1);
dataId.push(inx);
dataId = dataId.join("-");
$(this).attr("id", dataId);
if(isParagraph(data.tagName)) {
$(this).text(inx);
}
}
else if (data.value) {
var dataValue = data.value.split("-");
dataValue.splice(-1, 1);
dataValue.push(inx);
dataValue = dataValue.join("-");
$(this).val(dataValue);
}
});
}
function isParagraph(tagName){
return tagName == "P";
};
<div id="container-1" class="paragraphs">
<div id="header-container-id-1" class="id-holder">
<h4>Header</h4>
</div>
<div id="paragraph-container-id-1" class="id-holder">
<p id="id-1" class="id-holder">1</p>
</div>
<button value="#container-1" class="id-holder">delete</button>
</div>
<div id="container-2" class="paragraphs">
<div id="header-container-id-2" class="id-holder">
<h4>Header</h4>
</div>
<div id="paragraph-container-id-2" class="id-holder">
<p id="id-2" class="id-holder">2</p>
</div>
<button value="#container-2" class="id-holder">delete</button>
</div>
<div id="container-3" class="paragraphs">
<div id="header-container-id-3" class="id-holder">
<h4>Header</h4>
</div>
<div id="paragraph-container-id-3" class="id-holder">
<p id="id-3" class="id-holder">3</p>
</div>
<button value="#container-3" class="id-holder">delete</button>
</div>
<div id="container-4" class="paragraphs">
<div id="header-container-id-4" class="id-holder">
<h4>Header</h4>
</div>
<div id="paragraph-container-id-4" class="id-holder">
<p id="id-4" class="id-holder">4</p>
</div>
<button value="#container-4" class="id-holder">delete</button>
</div>
<div id="container-5" class="paragraphs">
<div id="header-container-id-5" class="id-holder">
<h4>Header</h4>
</div>
<div id="paragraph-container-id-5" class="id-holder">
<p id="id-5" class="id-holder">5</p>
</div>
<button value="#container-5" class="id-holder">delete</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
If I understand your question correctly, you're looking to more elegantly identify which elements have an id of the form "__-id-#" or simply "id-#".
If this is the case, take a look at some more advanced jQuery selectors. One in particular which might meet your needs is the Attribute Contains Selector.
For instance, I think $(parent).find("[id*='id-']") might do what you're looking to do.
While I understand what you're attempting to do, I don't quite understand why you're doing this in the first place.
Unless there are restrictions that force you to structure your HTML like you did, well, don't. Aim for the simplest structure:
<div id="container-123" class="paragraphs">
<h4>Header</h4>
<p>1</p>
<button type="button">delete</button>
</div>
Remove the <div>s around the <h4> and the <p> unless you need them for some styling reason. The <button> doesn't need to know its ID, because it's a child element of the container, so you're delete handler could make use of that fact:
$(document.body).on("click", "button", function() {
$(this).closest('.paragraphs').remove();
});
If there are outside forces that require a specific ID (e.g. for linking to an anchor), keep that on the top container element. If your CSS targets elements by ID, refactor the CSS.
I would like to answer your question using javascript. In fact you don't need any of those id-s
I hope I'm not too late.
let buttons = Array.from(document.querySelectorAll(".id-holder"));
buttons.forEach(b => {
//for each button add an event listener
b.addEventListener("click", () => {
b.parentElement.parentElement.removeChild(b.parentElement);
resetNums();
});
});
function resetNums(){
// reseting the text inside the p
let btns = Array.from(document.querySelectorAll(".id-holder"));
btns.forEach((bt,i)=>{
let theP = bt.parentElement.querySelector("p");
theP.innerHTML = i+1;
})
}
<div>
<div>
<h4>Header1</h4>
</div>
<div>
<p>1</p>
</div>
<button class="id-holder">delete</button>
</div>
<div>
<div>
<h4>Header2</h4>
</div>
<div>
<p>2</p>
</div>
<button class="id-holder">delete</button>
</div>
<div>
<div>
<h4>Header3</h4>
</div>
<div>
<p>3</p>
</div>
<button class="id-holder">delete</button>
</div>
<div>
<div>
<h4>Header4</h4>
</div>
<div>
<p>4</p>
</div>
<button class="id-holder">delete</button>
</div>
<div>
<div>
<h4>Header5</h4>
</div>
<div>
<p>5</p>
</div>
<button class="id-holder">delete</button>
</div>

Get sister element using jQuery

Is there a way to get a next element from a current sister element? Sorry if confusing.
<div class="wrapper">
<div class="paDiv">
<div class="saDivOne">
</div>
</div>
<div class="paDivTwo">
<div class="saDivTwo">
</div>
</div>
</div>
<script>
$('.paDiv').each(function(){
htmlContent = $(this).children().html();
SisterDivContent = $(this).next('.paDivTwo').children().html();
console.log(SisterDivContent);
})
</script>
$('.paDiv').each(function(){
var SisterDivContent = $(this).parent().find('.saDivTwo').html();
alert(SisterDivContent);
});
You have to add some contents inside div class 'saDivTwo'. Otherwise you will get empty content only.
Demo:
http://jsfiddle.net/U8n7g/
Try using .sibling:
$('.paDiv').sibling('paDivTwo').html()

Binding a text containing javascript to innerHTML in a template

For a metro style app, in Windows 8, I have a list of article that i pass to a flip View Control. Each Article have a description text in HTML which contains javascript. I know we have to use this function to load unsafe content to innerHTML :
var someElement = document.getElementById('someElementID');
MSApp.execUnsafeLocalFunction(
function() { someElement.innerHTML = '<div onclick="console.log(\"hi\");">hi</div>' }
);
But how can i achieve that when my innerHTML property is within a template?
here is my template :
<div id="ItemTemplate" data-win-control="WinJS.Binding.Template">
<div class="itemDetail fragment">
<header aria-label="Header content" role="banner">
<!-- <button class="win-backbutton" aria-label="Back" disabled></button>-->
<h1 class="titlearea win-type-ellipsis">
<span class="pagetitle"></span>
</h1>
</header>
<section aria-label="Main content" role="main">
<article>
<img class="article-image" src="#" style="width: 300px; height: 200px;" data-win-bind="src: urlImage; alt: title" />
<div class="item-content" data-win-bind="innerHTML: description"></div>
</article>
</section>
</div>
</div>
for this flipVIew :
<div id="basicFlipView"
data-win-control="WinJS.UI.FlipView"
data-win-options="{itemTemplate:select('#ItemTemplate')}">
</div>
and here is how i Fill it :
var dataControl = document.getElementById("basicFlipView").winControl;
dataControl.itemDataSource = dataList.dataSource;
dataControl.currentPage = myState.index;
Thank you very much for your help
EDIT : As Dominic Hopton suggested I used a WinJS.Binding.initializer. This is a quite complex way of doing a binding. I've done this but it doesn't work properly. Do you see something wrong :
var toUnsafeHTML = WinJS.Binding.initializer(
function toUnsafeHTML(source, sourceProperty, dest, destProperty) {
function setUnsafeHTML() {
MSApp.execUnsafeLocalFunction(
function () { dest.innerHTML = source.innerHTML }
);
}
return WinJS.Binding.bind(source, {
innerHTML : setUnsafeHTML}
);
}
);
//
// Binding initializers have to be public, so publish this out
// via a namespace
//
WinJS.Namespace.define("TemplateControl", {
toUnsafeHTML: toUnsafeHTML
});
and in the html :
<div id="ItemTemplate" data-win-control="WinJS.Binding.Template">
<div class="itemDetail fragment">
<header aria-label="Header content" role="banner">
<!-- <button class="win-backbutton" aria-label="Back" disabled></button>-->
<h1 class="titlearea win-type-ellipsis">
<span class="pagetitle"></span>
</h1>
</header>
<section aria-label="Main content" role="main">
<article>
<img class="article-image" src="#" style="width: 300px; height: 200px;" data-win-bind="src: urlImage; alt: title" />
<div class="item-content" data-win-bind="innerHTML: TemplateControl.toUnsafeHTML"></div>
</article>
</section>
</div>
</div>
It never enter the setUnsafeHTML function...
I'm not sure this is even possible using databinding, at least not using any of several techniques I tested.
That being said...even if you COULD do this...if the articles you are loading are coming from the Internet, this would be a VERY bad idea.
If you load script from the network, you expose yourself to the possibility that it contains malicious code. There's a reason this limitation exists, which is to protect you (and more importantly, those who use your app) from potential exploits.
If you haven't already, please read the docs for execUnsafeLocalFunction, as they detail why attempting to inject script from the web in the local app context is a bad idea:
http://msdn.microsoft.com/en-us/library/windows/apps/Hh767331.aspx
See also (the section titled "Dynamically adding HTML"):
http://msdn.microsoft.com/en-us/library/windows/apps/hh465380.aspx
and:
http://msdn.microsoft.com/en-us/library/windows/apps/hh465388.aspx
which lists the tags, attributes, and CSS properties that are considered safe or unsafe.
Hope that helps!

Categories