Given a structure like this:
<div class="portlet">
<div class="portlet-config">
<p>Some configuration</p>
</div>
<div class="portlet-header">Configurable portlet</div>
<div class="portlet-content">This has a configuration window. Click on pencil icon to open.</div>
</div>
First, I append these DIVs to portlet-header (to display some buttons)
<div class="portlet-button-container">
<div class="portlet-button portlet-btn-delete ui-icon ui-icon-close"></div>
<div class="portlet-button portlet-btn-toggle ui-icon ui-icon-minusthick"></div>
<div class="portlet-button portlet-btn-config ui-icon ui-icon-pencil"></div>
</div>
Then I apply a jquery-ui dialog() plugin to the portlet-config DIVs
$(".portlet-config").dialog({
autoOpen: false,
show: {
effect: "fade",
duration: 200
},
hide: {
effect: "fade",
duration: 500
},
modal: true,
buttons: {
Ok: function () {
$(this).dialog("close");
}
}
});
Then I add come click handlers
$(".portlet-btn-toggle").click(function () {
var icon = $(this);
icon.toggleClass("ui-icon-minusthick ui-icon-plusthick");
icon.closest(".portlet").find(".portlet-content").toggle();
});
$(".portlet-btn-delete").click(function () {
var icon = $(this);
icon.closest(".portlet").hide();
});
$(".portlet-btn-config").click(function () {
var icon = $(this);
icon.closest(".portlet").find(".portlet-config").dialog("open");
});
It seems that the portlet-config DIV could not be found when the user clicks on the pencil.
More precisely it seems that:
$(this) // OK, returns an object
$(this).closest(".portlet") // OK, returns an object
$(this).closest(".portlet").find(".portlet-config") // NOK, returns null
Here is a fiddle to reproduce the problem: http://jsfiddle.net/silenzioso/M6LmS/
Thanks in advance
Your call to $(".portlet-config").dialog is doing a little more than you expect it to. If you look in the DOM, you can see that the div has been moved out of its original location and added to the end of the document. Presumably it does this for the overlayed dialog effect.
You could consider putting a unique ID on the dialog div so that you can find it again. Perhaps you could use a data attribute to store the associated dialog div ID in the button.
<div class="portlet">
<div class="portlet-config" id="dialog1">
<p>Some configuration</p>
</div>
<div class='portlet-button' data-config="dialog1"></div>
</div>
...
var id = $(this).data('config');
var config = $('#'+id);
If You are dynamically creating new DOM elements in jQuery make sure You add event click on body or document or other element that is defined from the very first page display (I mean server response):
$('body').on('click', '.portlet-btn-config', function(e){
});
Related
I'm creating a fairly simple FAQ system to overhaul my company's outdated one. The page layout is very basic:
<div class="faq_c"> // Container
<div class="faq_q">Question Goes Here</div> // Question -- clicking this should open the Answer div in a dialog
<div class="faq_a">Answer Goes Here</div> // Answer
</div>
The faq_a class has display:none set in CSS to hide it.
What I'm wanting to do is have each faq_a load into a modal dialog when the parent faq_q class DIV is clicked. The structure of the modal should be:
Question
--------- // Horizontal Rule formatted with CSS
Answer
jQuery (Revised)
$(document).ready(function(){
$('.faq_a').each(function(){
$('.faq_a').dialog({
autoOpen: false,
modal: true,
resizable: false,
draggable: false,
overflow: scroll,
title: "Frequently Asked Question",
width: 500
});
$('.faq_q').click(function(){
$('.faq_a').dialog('open');
});
});
});
This isn't working exactly correctly. Instead of opening the single desired faq_a it's opening all of them. I also can't figure out how to get the desired layout inside the div.
Thanks in advance.
Looks like you just need to fix your selector:
jsFiddle
//var $dialog = $('<div>' + $('.faq_q') + '<hr>' + $('.faq_a') + '</div>'); // bad
var $dialog = $('div, .faq_q, hr, .faq_a');// good
$dialog.click(function() {
alert('clicked');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
click me
</div>
Is it possible to have a bootstrap (v3) popovers to have it's div loaded right at the start of pageload and not be destroyed when it is being toggled?
I have a popover content in a div:
<div id="popoverContent">
<h1>Stuff</h1>
<p>I'm in a popover!</p>
</div>
And a button that toggles the popover:
<a id="floating_tab" data-toggle="popover" data-placement="left">Button</a>
Here is my Javascript code that handles the button pushes:
<script>
var x = false;
$('[data-toggle=popover]').popover({
content: $('#popoverContent').html(),
html: true
}).click(function() {
if (x) {
$(this).popover('hide');
x = false;
}
else {
$(this).popover('show');
x = true;
}
});
</script>
The thing is, that when $(this).popover('show'); is called, a div is created. Something like this shows up in the inspect element (chrome):
<div class="popover fade left in" role="tooltip" id="popover460185" style="top: 430.5px; left: 2234px; display: block;"><div class="arrow" style="top: 50%;"></div><h3 class="popover-title" style="display: none;"></h3><div class="popover-content">
<h1>Stuff</h1>
<p>I'm in a popover!</p>
</div></div>
But when the button is clicked again, the whole div itself is removed and obliterated from the page.
Is it possible to have the popover div to be created during pageload (hidden though) and can be toggleable without having the div to be deleted?
As stated in the comments, it is not presently possible with Bootstrap 3. The Popover (which is an extension of the Tooltip) is dynamically created on show and detached (using jQuery.detach) from the DOM on hide.
It is probably best to roll your own JavaScript and simply utilize Bootstrap's CSS. However, you could easily patch the functionality using the Popover's event API -the following can be used as a starting place:
$(function () {
var content = $('#popover-content'), // Pre defined popover content.
popover = $('#popover-anchor').popover();
popover.on('inserted.bs.popover', function () {
var instance = $(this).data('bs.popover');
// Replace the popover's content element with the 'content' element
instance.$tip = content;
});
popover.on('shown.bs.popover', function () {
var instance = $(this).data('bs.popover');
// Remove the reference to 'content', so that it is not detached on hide
instance.$tip = null;
});
popover.on('hide.bs.popover', function () {
// Manually hide the popover, since we removed the reference to 'content'
content.removeClass('in');
content.addClass('out');
});
});
Codepen
My website is a blog where I have a page with all the posts on a single HTML page. The "posts" are just images inside divs and I need some information to be able to show and hide in side the parent div of the images. Heres how its set up:
HTML
<div class="posts">
<h3>mm/dd/yy<p class="preview">click to show more</p><p class="expand">click to show less</p></h3>
<h4>Title</h4><br>
<p class="expand">caption caption caption caption caption caption caption caption caption</p>
<div class="centertext">
<img class="post" src="path/to/image">
</div>
<br>
</div>
lil CSS
.expand{display: none;}
JS
$(document).ready(function(){
$(".posts").click(function(){
$('.expand').toggle();
$('.preview').toggle();
});
What ends up happening that I don't want to happen is that all images and their captions are hiding and showing when I just click one. Shown here or fullscreen here Someone please help me! Additional info: I am using JQuery and Bootstrap too
Change your JS to:
$(document).ready(function () {
$(".posts").click(function () {
$(this).find('.expand').toggle();
$(this).find('.preview').toggle();
});
});
Or more simple:
$(document).ready(function () {
$(".posts").click(function () {
$(this).find('.expand, .preview').toggle();
});
});
To toggle means, that you don't know the state. The best way is, to change a css-class or a data-attribute.
You can use event.target/this to refer the current object clicked and find child(expand/preview) of the object you clicked with find()
or
check for the children if it is .expand/.preview with function is() //not a better approach
$(document).ready(function () {
$(".posts").click(function () {
$(this).find('.expand').toggle();
$(this).find('.preview').toggle();
});
});
or
$(document).ready(function () {
$(".posts").click(function (event) {
$(event.target).find('.expand').toggle();
//check if target is .expand or its child then first go to its parent with .parents().eq() then apply find()
$(event.target).find('.preview').toggle();
//check if target is .preview or its child then first go to its parent with .parents().eq() then apply find()
});
});
I am trying to append items to a nested accordion dynamically when the user clicks a button. I am using the following code to create a nested accordion:
$(".accordion").accordion({
collapsible: true,
autoHeight: false,
animated: 'swing',
heightStyle: "content",
changestart: function(event, ui) {
child.accordion("activate", false);
}
});
var child = $(".child-accordion").accordion({
active:false,
collapsible: true,
autoHeight: false,
animated: 'swing'
});
In order to do this, I have found that I need to refresh the accordion using the following:
$('.accordion').accordion("refresh");
My problem is that when I try to refresh the inner accordion using:
$('.child-accordion').accordion("refresh");
I get the following:
Error: cannot call methods on accordion prior to initialization; attempted to call method 'refresh'
When I inspect the div that should be refreshed it has the following ids/classes:
DIV#shelf0sections.child-accordion.ui-accordion-content.ui-helper-reset.ui-...
I tried using the selector:
$('#shelf0sections .child-accordion').accordion("refresh");
instead which doesn't give an error, but nothing happens visually.
jsFiddle: http://jsfiddle.net/Mw9SA/3/
(Note that the first element in the list is just an example to see the nested accordion working, If you try to add sections to it, it won't work. Use the '+Shelf' button, then open the new accordion and use the '+Section' button.)
How about a more modular approach?
Fiddle or it didnt happen: http://jsfiddle.net/Varinder/24hsd/1/
Explanation
The idea is ( the same ) to create a brand new accordion element on the fly with correct events attached and appended somewhere in the DOM.
It's generaly more managable to have repeater HTML markup abstracted away in a template somewhere in DOM and use JS to reference it rather that building it from a string.
Heres the accordion template in the markup:
<div class="template">
<div class="accordion">
<h3 class="accordion-title">accordion title</h3>
<div class="accordion-content">
accordion content
</div>
</div>
</div>
Heres the full HTML markup - just in case:
<div class="page">
</div>
<div id="addShelf" class="button">+ Shelf</div>
<div id="addSection" class="button">+ Section</div>
<div class="template">
<div class="accordion">
<h3 class="accordion-title">accordion title</h3>
<div class="accordion-content">
accordion content
</div>
</div>
</div>
JS
Starting off by storing different accordion configurations:
var shelfConfig = {
collapsible: true,
autoHeight: false,
animated: "swing",
heightStyle: "content"
}
var shelfSectionConfig = {
active:false,
collapsible: true,
autoHeight: false,
animated: "swing"
}
Kepping a track of current accordion number and current accordion section number ( number of sections inside last accordion ) - might come in handy if you require a feature to remove an accordion shelf
var currentShelfNumber = 0;
var currentShelfSectionNumber = 0;
Chaching DOM elements, notice reference to the tempalte div
var $page = $(".page");
var $accordionTemplate = $(".template").children();
var $addSection = $("#addSection");
var $addShelf = $("#addShelf");
Creating a helper function that simply returns a cloned copy of the accordion template from the DOM
function getAccordionTemplate() {
return $accordionTemplate.clone();
}
Main function generateAccordion - it takes two arguments, accordionNumber to append current number in titles etc and accordionType to find out which accordion configuration to use.
With those parameters it will return a brand-spanking-new accordion with appropriate events attached which can then be append to the DOM
function generateAccordion( number, accordionType ) {
var $accordion = getAccordionTemplate();
var accordionTitle = "twerking bieber?";
if ( accordionType == "shelf" ) {
accordionTitle = "Shelf " + number;
} else {
accordionTitle = "Shelf Section";
}
$accordion.find("h3").text( accordionTitle );
var $accordionWithEvents = attachAccordionEvents( $accordion, accordionType );
return $accordionWithEvents;
}
Notice the call to another function attachAccordionEvents as the name suggests - this fella will attach events to the accordion element.
function attachAccordionEvents( $accordionElement, accordionType ) {
if ( accordionType == "shelf" ) {
$accordionElement.accordion( shelfConfig );
} else {
$accordionElement.accordion( shelfSectionConfig );
}
return $accordionElement;
}
Another helper function which makes sure "add section" button doesnt show up if there is no accordion shelf for it to work on
function manageSectionButton() {
if ( $page.children().length > 0 ) {
$addSection.show();
} else {
$addSection.hide();
}
}
Finaly events and logic:
$addShelf.on("click", function(e) {
e.preventDefault();
var newShelfNumber = currentShelfNumber + 1;
var $shelfElement = generateAccordion( newShelfNumber, "shelf" );
currentShelfNumber = newShelfNumber;
$page.append( $shelfElement );
manageSectionButton();
});
$addSection.on("click", function(e) {
e.preventDefault();
var newShelfSectionNumber = currentShelfSectionNumber + 1;
var $shelfSectionElement = generateAccordion( newShelfSectionNumber, "section" );
var $activeShelfElement = $page.children().last().find(".accordion-content");
$activeShelfElement.append( $shelfSectionElement );
});
... And thats about it.
Hope this helps,
Cheers
I want to refresh a <div> on the close of a jQuery UI Modal Dialog.
My code is:
var dialog = jQuery('#divPopup').dialog({
autoOpen: false,
height: 450,
width: 650,
modal: true,
open: function(event, ui) {
jQuery('body').css('overflow', 'hidden');
},
close: function(event, ui) {
jQuery('#divPopup').dialog('destroy').remove();
jQuery("#bodyId").load("http://www.xyz.com/ #bodyId");
}
});
But instead of replacing it, that adds the new <div> inside the old <div>:
<div id="bodyId">
<div id="bodyId">
New Response
</div>
</div>
I want to replace old div bodyId with new div bodyId.
Try to replace this:
jQuery("#bodyId").load("http://www.xyz.com/ #bodyId");
... with this:
jQuery("#bodyId").load("http://www.xyz.com/ #bodyId > *");
This works because you can use any selector after the URL. By using #bodyId > * instead of just #bodyId, you match everything that is inside the div, instead of the div itself.
You need this because .load() will not replace an element; it will append the result of the AJAX call to the element.
Alternatively, you could use .get() to load the data and manually perform the selection, like so:
$.get('http://www.xyz.com/', function(data) {
var newContent = $(data).find('#bodyId').children();
$('#bodyId').empty().append(newContent);
});
Examples of both methods are online here: http://jsfiddle.net/PPvG/47qz3/
You could also use jquery.get.
$.get('http://www.xyz.com/', function(data) {
$('#bodyId').html(data);
});
you may be use this code like
$('#bodyID').remove();
$('#bodyID').load();