Clone/Unclone in JQuery - javascript

I'm trying to 'clone' an image (showing it twice on the same page) as well as to hide it again on button clicks.
Is there a way to get it work using the function below?
$(".clone-button").on("click", function() {})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="cloneControls" class="card">
<h4 class="card-header">Double Power!</h4>
<div class="card-body">
<div class="text-center">
<button class="btn btn-dark btn-lg clone-button">
<span class="fa fa-ok"></span>
Clone
</button>
<button class="btn btn-primary btn-lg unclone-button">
<span class="fa fa-plus"></span>
Unclone
</button>
</div>
</div>
</div>
I have just started learning Javascript and JQuery. I already did some research, tried toggle, bootstrap clone, even created getElementID, however, none of my approaches seemed to work. Apparently I am understanding it wrong, can anybody give me some first advice please?

It is pretty easy using JQuery's clone method. Note that it produces duplicate IDs. You have to remove them yourself. clone does not copy within the DOM. You have to insert the new node subsequently.
Since almost every JQuery method returns the JQuery collection, you can chain method invokations without using variables.
$(".clone-button").on("click", function()
{
$('#to-clone')
.clone()
.addClass('cloned')
.attr('id',null) // we do not want duplicate IDs
.insertAfter('#to-clone');
});
$(".unclone-button").on("click", function()
{
$('.cloned').remove();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="cloneControls" class="card">
<h4 class="card-header">Double Power!</h4>
<img id="to-clone" src="https://via.placeholder.com/350x65">
<div class="card-body">
<div class="text-center">
<button class="btn btn-dark btn-lg clone-button">
<span class="fa fa-ok"></span>
Clone
</button>
<button class="btn btn-primary btn-lg unclone-button">
<span class="fa fa-plus"></span>
Unclone
</button>
</div>
</div>
</div>

Related

querySelector criteria based on class and ID at the same time

In this HTMl code :
<div class="modal__actions">
<button class="btn btn--passive">Cancel</button>
<button class="btn btn--success">Add</button>
</div>
<div class="modal" id="delete-modal">
<h2 class="modal__title">Are you sure?</h2>
<p class="modal__content">
Are you sure you want to delete this item? This action can't be made
undone!
</p>
<div class="modal__actions">
<button class="btn btn--passive">No (Cancel)</button>
<button class="btn btn--danger">Yes</button>
</div>
</div>
I am trying to reach to :
<button class="btn btn--passive">No (Cancel)</button>
item , I know there are different ways, but I am trying to use querySelector, I tried these commands but none of them selected what I was looking for:
const r1=document.querySelector('#delete-modal .btn btn--passive')
const r2=document.querySelector('#delete-modal, .btn btn--passive')
const r3=document.querySelector('.btn btn--passive, #delete-modal ')
Isn't it possible to use class and ID at the same time on querySelector ?
You should not have any space between the classes btn and btn--passive as they are for the same element. Also, you should prefix the class symbol for all the classes:
const r1=document.querySelector('#delete-modal .btn.btn--passive');
console.log(r1);
<div class="modal__actions">
<button class="btn btn--passive">Cancel</button>
<button class="btn btn--success">Add</button>
</div>
<div class="modal" id="delete-modal">
<h2 class="modal__title">Are you sure?</h2>
<p class="modal__content">
Are you sure you want to delete this item? This action can't be made
undone!
</p>
<div class="modal__actions">
<button class="btn btn--passive">No (Cancel)</button>
<button class="btn btn--danger">Yes</button>
</div>
</div>

how to stop iterating my like button inside my post

I am working on a post system with likes where the user can toggle the post`s like I have done everything correctly except the last step, the problem inside my v-for loop I fetch likes table from post-like relation(many to many since likes table has user_id and post_id) but it is iterating my button even when I add a condition look here-> duplicated like button, I have tried many things v-if, v-show I think the problem is with my algorithm I hope someone can fix that for me thanks.
<div class="panel panel-white post panel-shadow" v-for="post in posts" >
<div class="post-heading">
<div class="pull-left image">
<img v-bind:src="'img/profile/' + post.user.photo" class="img-circle avatar" alt="user profile image">
</div>
<div class="pull-left meta">
<div class="title h5">
<b>{{post.user.name}} </b>
made a post.
</div>
<h6 class="text-muted time">{{post.created_at | hour}}</h6>
</div>
</div>
<div class="post-description">
<p>{{post.content}}</p>
<div class="stats">
<button class="btn btn-default stat-item" #click.prevent="addLike(post.id)">
<i class="fa fa-thumbs-o-up" aria-hidden="false" style="color: blue" v-for="(like) in post.likes" v-bind:style="like.user_id===id && like.post_id===post.id?'color: blue;':'color: gray;'" > Like {{post.likes.length}}
</i> <!-- here is the duplicate problem-->
</button>
<a class="btn btn-default stat-item" #click.prevent>
<i class="fa fa-reply-all"> {{post.comments.length}}</i> Comments
</a>
</div>
</div>
<comment-input :post="post" :userId="id" :userPhoto="userPhoto"></comment-input>
<ul class="comments-list" v-for="comment in post.comments?post.comments:''">
<comments :comment="comment" :userId="id" :userPhoto="userPhoto"></comments>
</ul>
</div>
<hr>
</div>
</div>
Don't loop through the button element, try to use a method likedBythisUser to check if the current user liked the post in order to bind it to the button style :
methods:{
likedBythisUser(post,id){
return post.likes.find(like=>{
return like.user_id===id && like.post_id===post.id;
}) // return a boolean value
}
}
template :
<button class="btn btn-default stat-item" #click.prevent="addLike(post.id)">
<i class="fa fa-thumbs-o-up" aria-hidden="false" style="color: blue" bind:style="likedBythisUser(post,id)?'color: blue;':'color: gray;'" > Like {{post.likes.length}}
</i> <!-- here is the duplicate problem-->
</button>

bootstrap modal html content knockout binding not applying popover

When I use the popover control in my modal the bindings do not work.
Here is the default content :
<form id="a" class="form-horizontal" data-bind="submit: SaveModal">
<div class="modal-body modal-content-form">
Default Content
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary btn-modal-submit" value="Submit">
</div>
</form>
When I click my button
<button type="button" class="btn btn-info" data-toggle="modal" data-target="#modal" data-title="Information" btn-block'=""><i class="fa fa-print"></i>Quote Proposal</button>I get the new Content:
<form id="a" class="form-horizontal" data-bind="submit: SaveModal">
<div class="modal-body modal-content-form">
<div class="panel-group">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" href="#collapse001391ce-ebdb-4423-b525-40f97835fa53">Modal Controls</a>
</h4>
</div>
<div id="collapse001391ce-ebdb-4423-b525-40f97835fa53" class="panel-collapse collapse">
<div class="panel-body"><div class="row"><div class="col-sm-6">
<div class="form-group">
<label>Coverage Special</label>
<div class="input-group">
<span class="input-group-addon">$</span>
<input id="CoverageSpecial" name="CoverageSpecial" data-bind="value: CoverageSpecial" type="number" step="any" class="form-control control-font">
<span class="input-group-addon">
<a tabindex="0" data-toggle="popover" data-trigger="focus" data-placement="left" title="TextBox Numeric Help : FAQs" data-content="
This control is an html textbox of type (TextNumeric). The values
that are allowed are between a (Minimum) and a (Maximum)
integer. The (Precision) allowed will dictate the amount of
numbers after the decimal. It is (Required) and will
render a label with the (Name) value.
"><i class="fa fa-question-circle"></i></a>
</span>
</div>
<span class="help-block"></span>
</div>
</div></div></div>
<div class="panel-footer"></div>
</div>
</div>
</div></div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary btn-modal-submit" value="Submit">
</div>
</form>
The problem is that knockout does not work if I dynamically append content. Why?
Knockout doesn't listen to changes made to the DOM. It processes the DOM tree once (after you call applyBindings) and creates event listeners and subscriptions to make sure stuff gets updated once needed. Some bindings, like the with binding, can re-apply bindings to parts of the DOM when needed.
Here's an example of a very basic way to force knockout to re-apply bindings:
We swap out parts of the DOM by using an html binding and an observable that holds the partial HTML
After each swap, we re-apply bindings to the inner part of the element that has the html binding: you cannot apply bindings to an element twice; the outer element is already bound to our initial vm
This example serves to show how knockout works, and isn't the best solution. Managing multiple binding contexts by hand can get messy. I'd suggest creating a custom binding that does this for you. Also, this solution only supports partial views that have one parent element.
var content1 = "<h1 data-bind='text: label1'>test</h1>";
var content2 = "<h2 data-bind='text: label2'>test</h2>";
var partialContent = ko.observable(null);
var reapplyBindingsToPartial = function() {
var partialVM = {
label1: "Heading 1",
label2: "Heading 2"
};
var partialElement = document.querySelector(".js-partialView").firstChild;
ko.applyBindings(partialVM, partialElement);
};
var swap = function() {
if (partialContent() === content1) {
partialContent(content2)
} else {
partialContent(content1);
}
// By now, the `html` binding was re-evaluated
reapplyBindingsToPartial();
};
var vm = {
partialContent: partialContent,
swap: swap
};
ko.applyBindings(vm);
swap();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="js-partialView" data-bind="html: partialContent"></div>
<button data-bind="click: swap">
swap
</button>

Protractor + angular error - Element is not clickable at point

When trying to test a visible button on a modal window using protractor and angular, I receive the error following error:
UnknownError: unknown error: Element is not clickable at point (400, 234). Other element would receive the click: <div class="modal-footer">...</div>'.
I have tried resizing the window to a larger size in the before each statement, and have tried a scrollTo the top of the page before the click as well. Any suggestions?
Code:
it('should create a new portfolio when modal form is completed', function () {
portfolio_create_btn.first().click().then();
element(by.model('portfolios.portName')).sendKeys('Test');
element(by.css('#portfolio-modal-create-button')).click();
Tabs.filter(function (elem, index) {
return elem.getTagName('tab-heading').getText();
}).then(function (filteredElements) {
expect(filteredElements.length).toEqual(expect_tabs_len_start + 1);
});
});
Most of the HTML:
<div class="container-fluid">
<h1 class='port-title port-manager-header title custom-inline'>Portfolios</h1>
<div ng-controller="ModalCtrl" class='create-new-frame'>
<!--todo move to a partial or into $templateCache -->
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Create New Portfolio</h3>
</div>
<form name='eventForm' method="POST">
<div class="modal-body">
<input id='create-new-portfolio-input' class='form-control' ng-model='portfolios.portName'
placeholder='Portfolio name' ng-required='true' maxlength="35" focus-me="true">
<span class="help-inline" ng-show="notUnique">Portfolio name already used</span>
<!--
Private/Group selection to be used in future versions
<div ng-init="radioModel = 'Right'; portfolios.groupSelection = false" class="btn-group">
<label class="btn btn-primary" ng-model="radioModel" ng-click='portfolios.groupSelection = true' btn-radio="'Left'">Group</label>
<label class="btn btn-primary" ng-model="radioModel" ng-click='portfolios.groupSelection = false' btn-radio="'Right'">Private</label>
</div>
-->
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok(portfolios.portName)"
ng-disabled="eventForm.$invalid || notUnique" id='portfolio-modal-create-button'>
Create
</button>
<button class="btn btn-warning" ng-click="cancel()" id='portfolio-modal-cancel-button'>Cancel</button>
</div>
</form>
</script>
<button class="btn btn-sm btn-primary create-new-frame-btn" ng-click="open('sm')">Create New</button>
</div>
<div class="title port-title custom-inline pull-right">
<!-- <span class="text-muted">
Organization // user
</span> -->
</div>
</div>
It turned out that the test before the one causing problems was opening the modal and leaving it open, and then when this test tried to open a new modal, couldn't find the button to do so because the modal was already open. I didn't realize that the very first line of the test was causing the error until I looked more closely. Problem solved.

Use Bootstrap Button Group to Swap Divs

I'm creating a login / register form for a woocommerce shop.
The default woo template shows two side by side forms, one for new customers to register, one for existing customers to login. IMHO this sucks.
I want to use a button group above a single form that swaps out the login / register forms based on the users selection, this way only one option is presented at a time. Hence, I need to swap content, and apply/remove active classes to the appropriate buttons.
I've done the following:
1.) Added a twitter bootstrap button-group like so:
<div class="col-sm-4 col-sm-offset-4">
<div class="btn-group btn-group-justified">
<div class="btn-group">
<button type="button" id="login_click" class="btn btn-default active" data-toggle="button">Login</button>
</div>
<div class="btn-group">
<button type="button" id="register_click" class="btn btn-default">Register</button>
</div>
</div>
</div>
2.) Wrapped the two forms in bootstrap classes and added IDs for simple targeting.
<div id="login_form" class="col-sm-4 col-sm-offset-4">
// login form
</div>
<div id="register_form" clas="col-sm-4 col-sm-offset-4">
//register form
</div>
I know there are built in jQuery plugins for accomplishing this. I've tried using the .active class without success. I also tried using data-toggle="button" and use the .toggle() method without success. I can't wrap my head around the appropriate jQuery, I either end up with both buttons toggled, or no buttons toggled.
Could someone guide me in the right direction?
You can just set some jQuery to hide/show the form divs:
$('#switch-forms .btn').on('click', function() {
$('#switch-forms .btn').removeClass('active');
$(this).addClass('active');
});
$('#login_click').on('click', function() {
$('#register_form').hide();
$('#login_form').show();
});
$('#register_click').on('click', function() {
$('#login_form').hide();
$('#register_form').show();
});
JS Fiddle: http://jsfiddle.net/ezrafree/HZbvA/
Also, you misspelled the class attribute on button#register_click. Updated markup is:
<div class="row">
<div class="col-sm-4 col-sm-offset-4">
<div id="switch-forms" class="btn-group btn-group-justified">
<div class="btn-group">
<button type="button" id="login_click" class="btn btn-default active">Login</button>
</div>
<div class="btn-group">
<button type="button" id="register_click" class="btn btn-default">Register</button>
</div>
</div>
</div>
</div>
<div class="row">
<div id="login_form" class="col-sm-4 col-sm-offset-4">
<p>Login Form</p>
</div>
<div id="register_form" class="col-sm-4 col-sm-offset-4">
<p>Register Form</p>
</div>
</div>
For anyone interested I made it work. Not the "bootstrap way" but it works as desired. Someone with better jQuery chops could certainly simplify this.
<script>
$(document).ready(function() {
var login_btn = $('#login_click');
var register_btn = $('#register_click');
var register_form = $('#registration_form');
var login_form = $('#login_form');
// set defaults
register_form.addClass("hidden");
login_btn.addClass("active");
// events for register button
register_btn.on("click", function(){
login_form.addClass("hidden");
login_btn.removeClass("active");
register_btn.addClass("active");
register_form.removeClass("hidden");
});
//events for login button
login_btn.on("click", function(){
register_form.addClass("hidden");
register_btn.removeClass("active");
login_btn.addClass("active");
login_form.removeClass("hidden");
});
});
</script>
Code updated
No jQuery, you could do it with bootstrap collapse.
try this
<div class="col-sm-4 col-sm-offset-4">
<div class="btn-group btn-group-justified">
<div class="btn-group">
<button type="button" id="login_click" class="btn btn-default" data-toggle="collapse" data-target=".class1">Login</button>
</div>
<div class="btn-group">
<button type="button" id="register_click" class="btn btn-default" data-toggle="collapse" data-target=".class1">Register</button>
</div>
</div>
</div>
<div class="col-sm-4 col-sm-offset-4">
<div class="class1 collapse in">123</div>
<div class="class1 collapse">321</div>
</div>
cannot comment in feed. there right way to use toggleClass
not good
$('#switch-forms .btn').on('click', function() {
$('#switch-forms .btn').removeClass('active');
$(this).addClass('active');
});
good
$('#switch-forms .btn').on('click', function() {
$('#switch-forms .btn').toggleClass('active');
});

Categories