Reset jQuery DOM element - javascript

I have the a method and the following code to get an array id divs
arr = $('.card.recipe-slider');
which returns me (for the first time)
[<div class=​"card recipe-slider active" data-id=​"1">​…​</div>​,
<div class=​"card recipe-slider" data-id=​"2">​…​</div>​,
<div class=​"card recipe-slider" data-id=​"3">​…​</div>​]
But when I call the same method again, ( for the second time), my Jquery DOM array gets duplicated as follows
[<div class=​"card recipe-slider active" data-id=​"1">​…​</div>​,
<div class=​"card recipe-slider" data-id=​"2">​…​</div>​,
<div class=​"card recipe-slider" data-id=​"3">​…​</div>​
<div class=​"card recipe-slider" data-id=​"1">​…​</div>​,
<div class=​"card recipe-slider" data-id=​"2">​…​</div>​,
<div class=​"card recipe-slider" data-id=​"3">​…​</div>​
]
So my question is how can I avoid this duplication?
I tried followings
1 ) make the array blank
arr = []
... code
2 ) Get the unique
$.unique($('.card.recipe-slider'))
3 ) Clearing the array first
$('.card.recipe-slider').empty();
arr = $('.card.recipe-slider')
4 ) and I have seen some solutions with cloning and replacing , which I'm not quite clear and don't know if that's the way to go.
Edit
Complete code , almost... :), this works as a wizard where each div will display when user clicks next
#html
<div class='card recipe-slider active' data-id='1'>
.. html
<a class="btn btn-warning button-full button-large icon-left next">Next..</a>
</div>
<div class='card recipe-slider' data-id='2'>
.. html
<a class="btn btn-warning button-full button-large icon-left next">Next..</a>
</div>
<div class='card recipe-slider' data-id='3'>
.. html
<a class="btn btn-warning button-full button-large icon-left next">Next..</a>
</div>
JS code
$(document).on('click', 'a.next', function(e){
arr = [];
arr = $('.card.recipe-slider');
current_card = $(this).closest('.card')[0];
id = current_card.dataset.id;
$(arr[id]).addClass('active');
$(current_card).removeClass('active');
})

Related

Add a number for each data-toggle="modal" and data-target="exampleModal" in a generated HTML code

I have some mapped json data to display the results in a container. Each list from the generated html must open a separate modal window. To do this, I need to associate a number to each data-toggle="modal" and to each data-target="exampleModal" in the generated code.
I tried to add in data-modal="modal${res[i]} but I don't get a number this way.
The generated code:
const res = some.d.results; //arr of objects
let ul = document.querySelector('#test');
const html = res.map(el=> {
for (i = 1; i < res.length; i++) {
return `<li class="box-top box-top--feat" type="button" data-toggle="modal${res[i]}" data-target="exampleModal${res[i]}">
<a class="box-top__content" href="#">
<div class="box-top__title__img2">
<img class="availableImgs" alt="" src="${res.dirRef}${'/'}${res.fileRef}" />
</div>
<h2 class="box-top__title">${res.PersonA.Person}</h2>
<h3 class="box-top__work">${res.Title}</h3>
</a>
</li>
<div class="modal fade" id="exampleModal${res[i]}" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body">
<p>${res.DescA.PersA]}</p>
</div>
</div>
</div>
</div>`;
}
}).join("");
What is the proper way to add a number here?
You seem to be looping over res multiple times, once with map() and once with for(...). But then your for-loop is returning on the first iteration and therefore not reaching subsequent iterations.
You can include an index in your map(): res.map((el,i) => {...} and then use that instance of i, rather than a separate for-loop.

sorting bootstrap modal-body elements in Javascript/Jquery when the page loads

I am working on the fiddle in which I want to sort multiple rows (Row1 having def and Assign a Computer Section, Row2 having abc and Assign a Computer Section, etc) coming from Bootstrap Modal.
At this moment, the rows are not sorted in the modal. The HTML/Bootstrap code which I have used in order to create the modal is :
<div class="row-computerlabel form-group clearfix">
<div class="editcomputerlabel col-sm-5">abc</div>
<div class="assigncomputerlabel col-sm-5">
<div class="btn-group bootstrap-select show-tick computerlabelscomputerselector">
<button type="button" class="btn dropdown-toggle btn-default" data-toggle="dropdown" title="Assign a computer"><span class="filter-option pull-left">Assign a computer</span> <span class="bs-caret"><span class="caret"></span></span></button>
<div class="dropdown-menu open">
<ul class="dropdown-menu inner" role="menu"></ul>
</div>
<select class="computerlabelscomputerselector selectpicker" multiple="" title="Assign a computer" tabindex="-98"></select>
</div>
</div>
<div class="deletecomputerlabel col-sm-2"><button class="btn btn-link btn-delete" data-task="deletelabel" title="Delete group" type="button"><i class="fa fa-trash-o"></i></button></div>
</div>
Problem Statement:
I am wondering what plain Javascript or Jquery code I need to add above so that all the contents in the Bootstrap Modal get sorted meaning abc, def, jkl text should show up first with their assigned computers in the fiddle when the page loads.
You could use the sort function of JavaScript.
jQuery
$(document).ready(function(){
var rowComputer = $('.row-computerlabel');
rowComputer.sort(function(a,b){
var label1 = $(a).children('.editcomputerlabel').text();
var label2 = $(b).children('.editcomputerlabel').text();
return label1 >= label2;
});
rowComputer.appendTo('#computerlabeltable');
});
This piece of code is really simple. You have in the rowComputer variable all your rows.
You apply the sort function on your array and you need to specify the condition of your sorting (here it needs to be sorted alphabetically).
Finally, you append your array containing your rows in the div englobing all yours rows.
jsFiddle
Here is a jFiddle link : http://jsfiddle.net/Lqam4g2u/

Appending rows to nested rows issue?

I'm making a table with nested row's.
The thing is that when I append a child row to a parent row all other parent rows append a child row also.
Use function:
$scope.templates=[{src:'template'}];
$scope.include = function(templateURI) {
$scope.templates.push({src:templateURI});
}
Append row:
<button class="btn btn-default btn-sm ng-scope" ng-click="include('rowInRow.html')">
<i class="glyphicon glyphicon-upload"></i>
</button>
Show template:
<div ng-repeat="template in templates">
<div ng-include="template.src">My template will be visible here</div>
</div>
Can somebody give me a hint?
I tried to do it myself but I didn't find what I need.
Try this: http://plnkr.co/edit/ZzPF7UFjKyp2tqn27cf4?p=preview
All of the projects are sharing the templates collection. Solve this by giving each project its own templates array and iterating through that.
Make the include function into:
$scope.include = function(project, templateURI) {
if (!project.templates)
project.templates = [];
project.templates.push({src:templateURI});
}
Call it like this:
<button class="btn btn-default btn-sm ng-scope" ng-click="include(project, 'rowInRow.html')">
<i class="glyphicon glyphicon-upload"></i>
</button>
Show it like this:
<div ng-repeat="template in project.templates">
<div ng-include="template.src">My template will be visible here</div>
</div>

jquery modal: closing a modal and then having it available as a clickable option

I been scratching my head on this one for a while.
Writing a plugin in grails that calls on bootstrap-mini.js and most of its css. Everything works fine. The issue I am having is I have a remote form which onComplete runs java script:
https://github.com/vahidhedayati/ml-test/blob/master/grails-app/views/mailingListModal/_modalcreate.gsp
<g:javascript>
function ${controller}CloseModal() {
var myClone=$('#BuildModal${id}').clone();
$('#BuildModal${id}').dialog().dialog('close');
$(".modal-backdrop").hide();
$('body').removeClass('modal-open');
//var myCloner = myClone.clone();
$('#${divId}1').hide().append(myClone);
//$('body').append(myClone);
<g:if test="${!disablecheck.equals('true') }">
var controller="${controller }";
var divId="${divId }";
$.get('${createLink(controller:"MailingListEmail", action: "getAjaxCall")}?ccontroller='+controller+'&divId='+divId,function(data){
$('#${divId}').hide().html(data).fadeIn('slow');
});
</g:if>
}
</g:javascript>
The bits at the top of the function is all the things I have tried so far.
https://github.com/vahidhedayati/ml-test/blob/master/grails-app/views/mailingListEmail/contactclients.gsp
<div class="tbutton">
<button href="#BuildModalSENDERS" class="btn btn-block btn-success" role="button" data-toggle="modal" title="Configure New Sender">
New Sender?</button>
<div id="mailerSenders1">
<g:render template="/mailingListModal/modalcreate" model="[title:'Add Senders Email', controller: 'mailingListSenders', callPage: 'form' , divId: 'mailerSenders', id: 'SENDERS' ]" />
</div>
And finally modelForm which is included on the top of the modalcreate.gsp (now shown)
<div class="modal fade" id="BuildModal${id}" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<g:formRemote id="${controller}" name="urlParams" class="form-horizontal" url="[controller:controller, action:'save']"
update="BuildModal${id}" onComplete="${controller}CloseModal()"
>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">x</button>
<h3>${title }</h3>
</div>
<div class="modal-body">
<div class="form-group">
<g:render template="/${controller }/${callPage }"/>
<g:submitToRemote class="myformsubmit" url="[controller:controller, action:'save']" update="BuildModal${id}" onComplete="${controller}CloseModal()" value="Create" />
</div>
</div>
</g:formRemote>
</div>
</div>
</div>
</div>
So it is a remote Form that submits can calls the above CloseModal
The question is when I Close this how do I make it available again when the user clicks the button to create new email ?
After adding all the cloning at the top of java script the only difference I was able to make was to make it display the backdrop on 2nd click so it went black on 2nd click but did not show up the modal content.
ok got it working by doing this:
<button href="#BuildModalSENDERS" class="btn btn-block btn-success" role="button" data-toggle="modal" title="Configure New Sender"
Now adding
onClick="runCheck()"> .....
<g:javascript>
function runCheck() {
$('#mailerSenders1').show();
}
</g:javascript>
That seems to work fine, it now loads up the page, just to add when I did body it just loaded it up again from the commented out attempts, modal.hide etc did not work and the hide attempts just showed it up under some other layers of the same page.. anyways this works fine now. sorry

Twitter bootstrap collapse: change display of toggle button

I am using Twitter Bootstrap to create collapsible sections of text. The sections are expanded when a + button is pressed. My html code as follows:
<div class="row-fluid summary">
<div class="span11">
<h2>MyHeading</h2>
</div>
<div class="span1">
<button type="button" class="btn btn-success" data-toggle="collapse" data-target="#intro">+</button>
</div>
</div>
<div class="row-fluid summary">
<div id="intro" class="collapse">
Here comes the text...
</div>
</div>
Is there a way to change the button to display - instead of + after the section is expanded (and change back to + when it is collapsed again)?
Additional information: I hoped there would be a simple twitter-bootstrap/css/html-based solution to my problem. All responses so far make use of JavaScript or PHP. Because of this I want to add some more information about my development environment: I want to use this solution inside a SilverStripe-based (version 3.0.5) website which has some implications for the use of both PHP as well as JavaScript.
try this. http://jsfiddle.net/fVpkm/
Html:-
<div class="row-fluid summary">
<div class="span11">
<h2>MyHeading</h2>
</div>
<div class="span1">
<button class="btn btn-success" data-toggle="collapse" data-target="#intro">+</button>
</div>
</div>
<div class="row-fluid summary">
<div id="intro" class="collapse">
Here comes the text...
</div>
</div>
JS:-
$('button').click(function(){ //you can give id or class name here for $('button')
$(this).text(function(i,old){
return old=='+' ? '-' : '+';
});
});
Update With pure Css, pseudo elements
http://jsfiddle.net/r4Bdz/
Supported Browsers
button.btn.collapsed:before
{
content:'+' ;
display:block;
width:15px;
}
button.btn:before
{
content:'-' ;
display:block;
width:15px;
}
Update 2 With pure Javascript
http://jsfiddle.net/WteTy/
function handleClick()
{
this.value = (this.value == '+' ? '-' : '+');
}
document.getElementById('collapsible').onclick=handleClick;
Here's another CSS only solution that works with any HTML layout.
It works with any element you need to switch. Whatever your toggle layout is you just put it inside a couple of elements with the if-collapsed and if-not-collapsed classes inside the toggle element.
The only catch is that you have to make sure you put the desired initial state of the toggle. If it's initially closed, then put a collapsed class on the toggle.
It also requires the :not selector, so it doesn't work on IE8.
HTML example:
<a class="btn btn-primary collapsed" data-toggle="collapse" href="#collapseExample">
<!--You can put any valid html inside these!-->
<span class="if-collapsed">Open</span>
<span class="if-not-collapsed">Close</span>
</a>
<div class="collapse" id="collapseExample">
<div class="well">
...
</div>
</div>
Less version:
[data-toggle="collapse"] {
&.collapsed .if-not-collapsed {
display: none;
}
&:not(.collapsed) .if-collapsed {
display: none;
}
}
CSS version:
[data-toggle="collapse"].collapsed .if-not-collapsed {
display: none;
}
[data-toggle="collapse"]:not(.collapsed) .if-collapsed {
display: none;
}
JS Fiddle
Add some jquery code, you need jquery to do this :
<script>
$(".btn[data-toggle='collapse']").click(function() {
if ($(this).text() == '+') {
$(this).text('-');
} else {
$(this).text('+');
}
});
</script>
All the other solutions posted here cause the toggle to get out of sync if it is double clicked. The following solution uses the events provided by the Bootstrap framework, and the toggle always matches the state of the collapsible element:
HTML:
<div class="row-fluid summary">
<div class="span11">
<h2>MyHeading</h2>
</div>
<div class="span1">
<button id="intro-switch" class="btn btn-success" data-toggle="collapse" data-target="#intro">+</button>
</div>
</div>
<div class="row-fluid summary">
<div id="intro" class="collapse">
Here comes the text...
</div>
</div>
JS:
$('#intro').on('show', function() {
$('#intro-switch').html('-')
})
$('#intro').on('hide', function() {
$('#intro-switch').html('+')
})
That should work for most cases.
However, I also ran into an additional problem when trying to nest one collapsible element and its toggle switch inside another collapsible element. With the above code, when I click the nested toggle to hide the nested collapsible element, the toggle for the parent element also changes. It may be a bug in Bootstrap. I found a solution that seems to work: I added a "collapsed" class to the toggle switches (Bootstrap adds this when the collapsible element is hidden but they don't start out with it), then added that to the jQuery selector for the hide function:
http://jsfiddle.net/fVpkm/87/
HTML:
<div class="row-fluid summary">
<div class="span11">
<h2>MyHeading</h2>
</div>
<div class="span1">
<button id="intro-switch" class="btn btn-success collapsed" data-toggle="collapse" data-target="#intro">+</button>
</div>
</div>
<div class="row-fluid summary">
<div id="intro" class="collapse">
Here comes the text...<br>
<a id="details-switch" class="collapsed" data-toggle="collapse" href="#details">Show details</a>
<div id="details" class="collapse">
More details...
</div>
</div>
</div>
JS:
$('#intro').on('show', function() {
$('#intro-switch').html('-')
})
$('#intro').on('hide', function() {
$('#intro-switch.collapsed').html('+')
})
$('#details').on('show', function() {
$('#details-switch').html('Hide details')
})
$('#details').on('hide', function() {
$('#details-switch.collapsed').html('Show details')
})
I liked the CSS-only solution from PSL, but in my case I needed to include some HTML in the button, and the content CSS property is showing the raw HTML with tags in this case.
In case that could help someone else, I've forked his fiddle to cover my use case: http://jsfiddle.net/brunoalla/99j11h40/2/
HTML:
<div class="row-fluid summary">
<div class="span11">
<h2>MyHeading</h2>
</div>
<div class="span1">
<button class="btn btn-success collapsed" data-toggle="collapse" data-target="#intro">
<span class="show-ctrl">
<i class="fa fa-chevron-down"></i> Expand
</span>
<span class="hide-ctrl">
<i class="fa fa-chevron-up"></i> Collapse
</span>
</button>
</div>
</div>
<div class="row-fluid summary">
<div id="intro" class="collapse">
Here comes the text...
</div>
</div>
CSS:
button.btn .show-ctrl{
display: none;
}
button.btn .hide-ctrl{
display: block;
}
button.btn.collapsed .show-ctrl{
display: block;
}
button.btn.collapsed .hide-ctrl{
display: none;
}
My following JS solution is better than the other approaches here because it ensures that it will always say 'open' when the target is closed, and vice versa.
HTML:
<a href="#collapseExample" class="btn btn-primary" data-toggle="collapse" data-toggle-secondary="Close">
Open
</a>
<div class="collapse" id="collapseExample">
<div class="well">
...
</div>
</div>
JS:
$('[data-toggle-secondary]').each(function() {
var $toggle = $(this);
var originalText = $toggle.text();
var secondaryText = $toggle.data('toggle-secondary');
var $target = $($toggle.attr('href'));
$target.on('show.bs.collapse hide.bs.collapse', function() {
if ($toggle.text() == originalText) {
$toggle.text(secondaryText);
} else {
$toggle.text(originalText);
}
});
});
Examples:
$('[data-toggle-secondary]').each(function() {
var $toggle = $(this);
var originalText = $toggle.text();
var secondaryText = $toggle.data('toggle-secondary');
var $target = $($toggle.attr('href'));
$target.on('show.bs.collapse hide.bs.collapse', function() {
if ($toggle.text() == originalText) {
$toggle.text(secondaryText);
} else {
$toggle.text(originalText);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet"/>
<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<a href="#collapseExample" class="btn btn-primary" data-toggle="collapse" data-toggle-secondary="Close">
Open
</a>
<div class="collapse" id="collapseExample">
<div class="well">
...
</div>
</div>
JS Fiddle
Other benefits of this approach:
the code is DRY and reusable
each collapse button stays separate
you only need to put one change into the HTML: adding the data-toggle-secondary attribute
I guess you could look inside your downloaded code where exactly there is a + sign (but this might not be very easy).
What I'd do?
I'd find the class/id of the DOM elements that contain the + sign (suppose it's ".collapsible", and with Javascript (actually jQuery):
<script>
$(document).ready(function() {
var content=$(".collapsible").html().replace("+", "-");
$(".collapsible").html(content));
});
</script>
edit
Alright... Sorry I haven't looked at the bootstrap code... but I guess it works with something like slideToggle, or slideDown and slideUp... Imagine it's a slideToggle for the elements of class .collapsible, which reveal contents of some .info elements. Then:
$(".collapsible").click(function() {
var content=$(".collapsible").html();
if $(this).next().css("display") === "none") {
$(".collapsible").html(content.replace("+", "-"));
}
else $(".collapsible").html(content.replace("-", "+"));
});
This seems like the opposite thing to do, but since the actual animation runs in parallel, you will check css before animation, and that's why you need to check if it's visible (which will mean it will be hidden once the animation is complete) and then set the corresponding + or -.
Easier with inline coding
<button type="button" ng-click="showmore = (showmore !=null && showmore) ? false : true;" class="btn float-right" data-toggle="collapse" data-target="#moreoptions">
<span class="glyphicon" ng-class="showmore ? 'glyphicon-collapse-up': 'glyphicon-collapse-down'"></span>
{{ showmore !=null && showmore ? "Hide More Options" : "Show More Options" }}
</button>
<div id="moreoptions" class="collapse">Your Panel</div>
Some may take issue with changing the Bootstrap js (and perhaps validly so) but here is a two line approach to achieving this.
In bootstrap.js, look for the Collapse.prototype.show function and modify the this.$trigger call to add the html change as follows:
this.$trigger
.removeClass('collapsed')
.attr('aria-expanded', true)
.html('Collapse')
Likewise in the Collapse.prototype.hide function change it to
this.$trigger
.addClass('collapsed')
.attr('aria-expanded', false)
.html('Expand')
This will toggle the text between "Collapse" when everything is expanded and "Expand" when everything is collapsed.
Two lines. Done.
EDIT: longterm this won't work. bootstrap.js is part of a Nuget package so I don't think it was propogating my change to the server. As mentioned previously, not best practice anyway to edit bootstrap.js, so I implemented PSL's solution which worked great. Nonetheless, my solution will work locally if you need something quick just to try it out.
You do like this.
the function return the old text.
$('button').click(function(){
$(this).text(function(i,old){
return old=='Read More' ? 'Read Less' : 'Read More';
});
});
Applied and working in Bootstrap 5.0.1.
Using simple jQuery
jQuery('button').on( 'click', function(){
if(jQuery(this).hasClass('collapsed')){
jQuery(this).html('+');
} else {
jQuery(this).html('-');
}
});
You can also use font awesome or HTML instead of +/- signs.

Categories