Collapse Panel Using Header and Header Text - javascript

I have a collapsible panel working currently using the following HTML:
<div class="panel panel-entity panel-default>
<div class="panel-heading" onclick="{ $(event.target).siblings('.panel-body').slideToggle('slow'); }">
<span class="panel-heading-text">#Model.RoleName</span>
</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="entity">
#*A bunch of form groups*#
</div>
</div>
</div>
</div>
However, this only allows the user to click on the panel header to collapse the panel, meaning that when they click on the text within the header, it will not collapse the panel.
Is there another approach I can take to allow the user to click anywhere within the header, including the text, to collapse the panel?

For any potential future readers, the way I solved this problem was by adding style="pointer-events: none;" to the span where the header text was stored.
If you are using a span element to add a class to the text within a collapsible panel header, this is the correct way to make the text click-through.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="panel panel-entity panel-default">
<div class="panel-heading" onclick="{ $(event.target).siblings('.panel-body').slideToggle('slow'); }">
<span class="panel-heading-text" style="pointer-events: none;">#Model.RoleName</span>
</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="entity">
#*A bunch of form groups*#
</div>
</div>
</div>
</div>

You need to remove the <span class="panel-heading-text"> tag. Since that tag is there, when you click on the text, you are actually clicking on that element and not the .panel-heading element.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="panel panel-entity panel-default">
<div class="panel-heading" onclick="{ $(event.target).siblings('.panel-body').slideToggle('slow'); }">
#Model.RoleName
</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="entity">
#*A bunch of form groups*#
</div>
</div>
</div>
</div>

Related

I can't add multiple text clicking by add button & showing some extra CSS

My first problem is that when I'm taking text from an input field and a div, the input field text is okay but the div text is showing extra CSS styling. Please see the screenshot.
<input id="accordion_input" type="text">
<div id="editableDiv" contenteditable=""></div>
The second problem is when I click the 'Add' button then the input and div text is appearing only one time. I want to add the text multiple times by clicking the button.
$(document).ready(function() {
$('#Add_btn').click(function() {
$('#accordion_body').text($('#editableDiv').html());
var x = document.getElementById("accordion_input").value;
document.getElementById("accordion_title").innerHTML = x;
});
$("#acc_main").append();
});
<input id="accordion_input" type="text">
<div id="editableDiv" contenteditable=""></div>
<div id="acc_main" contenteditable="false" class="accordion-main">
<div class="panel-group trash_removed" id="accordion" role="tablist" aria-multiselectable="true" contenteditable="false">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne" contenteditable="false">
<h4 class="panel-title">
<a id="accordion_title"></a>
</h4>
<div id="expandingCol" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
<div id="accordion_body" class="panel-body"></div>
</div>
</div>
</div>
</div>
</div>
<button onclick="myAccorFunction()" id="Add_btn">Add</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Firstly note that you have an onclick attribute referencing a function which doesn't exist which is causing an error. Remove that attribute. They shouldn't be used anyway.
Regarding the 'CSS styling' you refer to, this is due to the encoded HTML which is visible as you're attempting to add HTML to an element using the text() method. Technically you should use html() instead, but given that you want to add a new instance of the strings on each button click, use append() instead. Try this:
$(document).ready(function() {
$('#Add_btn').click(function() {
$('#accordion_body').append($('#editableDiv').html());
var x = $("#accordion_input").val();
$("#accordion_title").append(x);
});
});
<input id="accordion_input" type="text">
<div id="editableDiv" contenteditable=""></div>
<div id="acc_main" contenteditable="false" class="accordion-main">
<div class="panel-group trash_removed" id="accordion" role="tablist" aria-multiselectable="true" contenteditable="false">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne" contenteditable="false">
<h4 class="panel-title">
<a id="accordion_title"></a>
</h4>
<div id="expandingCol" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
<div id="accordion_body" class="panel-body"></div>
</div>
</div>
</div>
</div>
</div>
<button id="Add_btn">Add</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Also note that I converted the native JS to jQuery; if you've loaded it you may as well use it. I also removed the $("#acc_main").append(); line as it is useless code which does nothing at all.

Nested v-for in vuejs for accordian data

I am building a small application on VueJS 2.5.17 where I am having nested accordion data which I need to display through click events, I have a hierarchy of Root -> Roles -> Specialisation -> withRoles .... and so on. I am trying to get child elements on every click of their respective parents.
Following is my HTML Code:
<div class="panel-group" id="accordion1" v-for="items in accordianData">
<div class="panel my-panel-warning">
<div class="panel-heading">
<h4 class="panel-title">
<a style="color: #000; font-size: 14px" data-toggle="collapse" data-parent="#accordion1" :href="'#'+items.id">DOCUMENTED RELATIONSHIPS ({{count}})</a>
</h4>
</div>
<div :id="items.id" class="panel-collapse collapse">
<div class="my-panel-body">
<div class="my-panel-body">
<div class="panel-group" :id="items.id" >
<div class="panel my-panel-warning" v-for="child1 in roles">
<div class="panel-heading">
<a data-toggle="collapse" :data-parent="'#'+items.id" :id="'child'+child1.id" :href="'#role'+child1.id" #click="getSpecialisation(child1.id, child1.name)">{{child1.name+" (0)"}}</a>
</div>
<div class="my-panel-body">
<div :id="'role'+child1.id" class="panel-collapse collapse">
<div class="panel my-panel-warning" v-if="child1.id === child2.parent_id" v-for="child2 in specialisations[child1.name]">
<div class="panel-heading">
<a data-toggle="collapse" :data-parent="'#role'+child1.id" :id="'child2'+child2.id" :href="'#spec'+child2.id" #click="getWithRoles(child2.id)">{{child2.name+" (0)"}}</a>
</div>
<div class="my-panel-body">
<div :id="'spec'+child2.id" class="panel-collapse collapse">
<div class="my-panel-body">
.
.
.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
And calling following function in my methods:
getSpecialisation(id, name) {
axios.get('specialisations?company_id='+this.company_id+'&role_id='+id, {headers: getHeader()}).then(response => {
if(response.status === 200)
{
this.specialisations[name] = response.data.specialisations
}
})
},
But some how I am unable to display the data. Previously I tried v-for="child2 in specialisations" and in response I did this.specialisations = response.data.specialisations I was getting all similar child element for all parents I know this is wrong but just wanted to inform that I was getting data and my accordion was displaying child elements, but once I did according to above method getSpecialisation mentioned, I am unable to display the data.
I can see my data in vue console:
Suggest me a better way for this.
Thanks
Instead of this.specialisations[name] = response.data.specialisations try:
Vue.set(this.specialisations, name, response.data.specialisations)
That should trigger Vue's change-detection.
Ps. When you see lots of nesting, this might be good time to split a big component up into smaller components.

how do i display long text after click read more button with shorted text?

I'm using an accordion panel for long comments in my blog. Now I want to add long text to short text and show the full text with this, but I have a problem. If I click the show button, it shows at a newline.
jsfiddle snippet
<div class="panel-group" id="accordion">
<div class="panel panel-default text-left" >
<div>
<div style="color:#000;" class="panel-body text-left"><br>This is short comment for my stack...</div>
</div>
</div>
<div class="panel" >
<div id="collapse2" class="clearfix panel-collapse collapse">
<div class="panel-body" style="color:#000;">overflow post and i hope i can find a good solution for this
</div>
</div>
<div class="panel-heading">'.
<h5><a class="btn btn-block" data-toggle="collapse" data-parent="#accordion" href="#collapse2">Show/Hide</a>
</h5>
</div>
</div>
</div>
I want to add another part to short text without newline.
Add the second part of your text in a span and hide it, then reveal it with JS:
function showMore()
{
if ($('#threedots').css('display')=='none')
{
//already showing, we hide
$('#threedots').show();
$('#full_desc').hide();
}
else
{
//show more
$('#threedots').hide();
$('#full_desc').show();
}
}//end function
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<div style="color:#000;" class="panel-body text-left"><br>This is short comment for my stack<span id="threedots">...</span><span id="full_desc" style="display:none">overflow post and i hope i can find a good solution for this</span></div>
<a class="btn btn-block" data-toggle="collapse" data-parent="#accordion" onclick="showMore()">Show/Hide</a>

How do I make Bootstrap popover work with HTML content in a seperate element

I am in the process of combining Bootstrap panels with Bootstrap popover functionality. The goal is to show a popover when the user hovers the panel's header. I've already got this to work, except that the data-content="" part becomes quite unmanageable when it has a lot of HTML inside.
Below is some sample HTML I am working with. The part that says "LOADS OF HTML" contains div's, table's, p's, etc.
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-briefcase fa-fw"></i>
<abbr title="Panel title" data-container="body" data-toggle="popover"
data-placement="bottom" data-trigger="hover" data-html="true"
data-content="<div>LOADS OF HTML HERE</div>">
Panel title
</abbr>
<div class="col-xs-6 col-md-4 pull-right" style="margin-top: -4px;">
<!-- some buttons go here -->
</div>
</div>
<!-- /.panel-heading -->
</div>
<!-- some panel content goes here -->
</div>
Other Bootstrap plugins solve this issue by allowing you to put the HTML in a separate element and then reference that element with a "data-target" attribute. Unfortunately, Popover does not support this. How do I mimic this behavior without writing element specific JavaScript?
Any text/HTML you want to display in the popover can be added in a DIV which has a display:none; CSS property to it.
You can pass a function to the content property of the popover options which gets the content from the hidden DIV. This way one doesn't need to reference by ID and insert script tags.
Here is an example http://jsfiddle.net/wb3n8/
HTML:
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Panel title 1</h3>
</div>
<div class="panel-body">Panel content 1</div>
<div class="my-popover-content">Here is some hidden content 1</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Panel title 2</h3>
</div>
<div class="panel-body">Panel content 2</div>
<div class="my-popover-content">Here is some hidden content 2</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Panel title 3</h3>
</div>
<div class="panel-body">Panel content 3</div>
<div class="my-popover-content">Here is some hidden content 3</div>
</div>
</div>
CSS:
.my-popover-content {
display:none;
}
Javascript:
$(document).ready(function () {
popoverOptions = {
content: function () {
// Get the content from the hidden sibling.
return $(this).siblings('.my-popover-content').html();
},
trigger: 'hover',
animation: false,
placement: 'bottom',
html: true
};
$('.panel-heading').popover(popoverOptions);
});
An elegant solution is to place the HTML-content inside a script-tag with an id and then add a data-target="element_id_goes_here" attribute to the element that will trigger the popover. Since you're using popover you should already have some generic JavaScript somewhere that initializes the plugin. You can extend this JavaScript with a few lines of code.
HTML
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-briefcase fa-fw"></i>
<abbr title="Panel title" data-container="body" data-toggle="popover"
data-placement="bottom" data-trigger="hover" data-html="true"
data-target="#my-popover-content">
Panel title
</abbr>
<div class="col-xs-6 col-md-4 pull-right" style="margin-top: -4px;">
<!-- some buttons go here -->
</div>
</div>
<!-- /.panel-heading -->
</div>
<!-- some panel content goes here -->
</div>
<script type="text/html" id="my-popover-content">
*** HTML CONTENT GOES HERE ***
</script>
JavaScript
$("[data-toggle='popover']").each(function(index, element) {
var contentElementId = $(element).data().target;
var contentHtml = $(contentElementId).html();
$(element).popover({
content: contentHtml
});
});
Solution, based on Martin Devillers post, but more flexible (passes all data-* tags into bootstrap js)
$("[data-toggle='popover']").each(function (index, element) {
var data = $(element).data();
if (data.target) {
var contentElementId = data.target;
var contentHtml = $(contentElementId).html();
data.content = contentHtml;
}
$(element).popover(data);
});
About Alexus1024 solution : I had to add a "#" before data.target in order to have jquery correctly selecting the target :
var contentElementId = "#"+data.target;

JQ UI Sortables: Stop some elements inside Sortable from being sorted

I have this sortable's structure (it's a portlet).
<div id="sortable">
<div class="row">
<div class="window"></div>
<div class="gripper_v"></div>
<div class="window"></div>
</div>
<div class="gripper_h"></div>
<div class="row">
<div class="window"></div>
<div class="gripper_v"></div>
<div class="window"></div>
</div>
<div class="gripper_h"></div>
<div class="row">
<div class="window"></div>
<div class="gripper_v"></div>
<div class="window"></div>
</div>
</div>
'window' elements are sortables. Grippers shouldn't be sortables. I've specified in the Sortable options:
{ items: '.window' }
But I'm seeing that windows are sorted over grippers while I drag, which I don't want to. I want grippers to be invisible to the Sortable.
EDIT: Grippers are used to resize windows in both X and Y axis. With the given html code i will get this portlet.
PORTLET IMAGE
The problem occurs when sorting between windows of the same row (".gripper_v")
I'm not sure exactly what you're trying to do here (a screenshot might help), is the "gripper" the part of the "window" where the user should click to drag?
If that's the case, try adding the gripper within the window element like this:
<div id="sortable">
<div class="window">
<div class="gripper"></div>
</div>
<div class="window">
<div class="gripper"></div>
</div>
</div>

Categories