Bootstrap dropdown not working after initial ajax form submission - javascript

I have a dropdown on my page, manager.php, here. Sorry for the formatting - bootstrap.:
<!-- Bootstrap -->
<script type="text/javascript" src="https://netdna.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="../../css/bootstrapstyle.css">
<!-- Bootstrap Dropdown Enhancements-->
<script type="text/javascript" src="../../js/dropdowns-enhancement.js"></script>
<link rel="stylesheet" href="../../css/dropdowns-enhancement.css">
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<div class="input-group-btn">
<button type="button" class="btn dropdown-toggle btn-primary" data-toggle="dropdown" aria-expanded="false">Search By <span class="caret"></span></button>
<ul id="searchBy" class="dropdown-menu" role="menu">
<li class="disabled">Search By...</li>
<li>cost</li>
<li>name</li>
</ul>
</div>
</div>
</div>
</div>
<div id="everything">
</div>
This code works fine when I load manager.php directly and the dropdown initializes, but this is not how I need the code to work.
The user begins on return.php; this page collects a bunch of data from the user and returns it to manager.php.
Once the user selects to do so on return.php, this code is run:
$.ajax({
type: 'POST',
url: 'manager.php',
data: {number:number, location:location, project:project, comments:comments},
success:function(data){
$('#everything').html(data);
}
});
The ajax call works correctly, and it loads the data returned from manager.php into the everything div. It passes along the data as expected. The only thing that DOESN'T work upon loading manager.php into the DIV is the drop-down. I need to understand what I'm doing wrong to cause this functionality so I can prevent doing it in the future.

you can't initialize the bootstrap component after page load by adding bootstrap clasaes. To do this you have to initialize it by your self
To initialize a dropdown write this code
$('.dropdown-toggle').dropdown();
after
$('#everything').html(data);
for more details: http://getbootstrap.com/javascript/#dropdowns

You need to manually reset the dropdown after you've loaded the data into the everything div. I've modified your AJAX call to show you where to put the call.
$.ajax({
type: 'POST',
url: 'manager.php',
data: {number:number, location:location, project:project, comments:comments},
success:function(data){
$('#everything').html(data);
$('#searchBy').dropdown();
}
});
The dynamic loading you're doing doesn't cause the DOM to reload forcing the drop down to be reinitialized. After you're AJAX call has completed, you can then reset the bootstrap drop down manually by calling .dropdown();.
EDIT
Generally functions in bootstrap for features are setup using a $( document ).ready() call. This function executes once, after the DOM has been loaded and only after the DOM has has been fully loaded. Since your manipulating the DOM, you are not causing the function to be triggered again, and you need to manually trigger the feature you need.
You also want to load your includes only once on each page. They need to on manager.php in order for the function be available when you go into your success method. I'd suggest using a template for your project so you manage all your includes in one place. Also, if your using manager.php as a page to be included in another page, it's okay if you don't have the reference to the JavaScript pieces won't work since you don't want users accessing that component on it's own.
The reload you are doing appears to be forcing the content to be re-added to the page, thus forcing the $( document ).ready() call in the included file to be re-executed. You can do this, but it's very inefficient.

So I'm not sure why this works, but it has so far:
I've modified my ajax call to reload bootstrap's .js file prior to executing the return.
function reload_js(src) {
$('script[src="' + src + '"]').remove();
$('<script>').attr('src', src + '?cachebuster='+ new Date().getTime()).appendTo('head');
}
$.ajax({
...
success:function(data){
reload_js('https://netdna.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js');
$('#everything').html(data);
}
});
For the bounty, can someone explain to me:
a.) Why do I need to force the reload of bootstrap.min.js?
b.) Why is this even necessary if I have a link to this file in BOTH files' <head> sections?
<!-- Bootstrap -->
<script type="text/javascript" src="https://netdna.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="../../css/bootstrapstyle.css">
I've also tried loading it in one, but not the other (so I don't load it twice,) and that doesn't do anything.
c.) Why does this work? What is it doing?

page will load DOM 1st time. ajax just update a part of page, so new elements you add wont have prop you defined. you need to reinit as you did or make something like this
http://hussain.io/2012/01/reinitializing-jquery-event-on-ajax-response/

I want to share my experience: I am doing dynamical multi layer dropdown menu, meaning that user can customize how many parents and children this menu has. So, after ajax submission, I empty the navbar where the menu is
$(document).find('.navbar-nav').empty();
And fill it with the new html like:
html.push("<li class="nav-item dropdown"> <a class="nav-link" href="#">" + val.PageName + ""); // It is OnTop
and append it to my navbar:
$(".navbar-nav").append(html.join(''));
and the dropdown item is there but it was not working. The reason is that you have to load all the js and css for that new html items again.
Here is the good example os static multilayer menu: https://github.com/kmlpandey77/bootnavbar
So, the main point is after you append new html to the DOM item, you need to reload the page so it to work, or load resources that is that new html items are using;
Here how to load after ajax and append process :
jQuery.ajaxSetup({ async: false });
$.get("wwwroot/bootnavbar/bootnavbar.css")
.done(function () {
// exists code
jQuery.ajaxSetup({
async: true
});
}).fail(function () {
// not exists code
jQuery.ajaxSetup({ async: true });
});

Related

how to dynamically add jquery mobile popup effect to links

In jquery mobile, I dynamically add a tags that is supposed to open a popup like in this example below. But since it is dynamically added, the jquery mobile effects don't affect it. How can I get it to work like this?
Thanks
Actions...
<div data-role="popup" id="popupMenu" data-theme="b">
<ul data-role="listview" data-inset="true" style="min-width:210px;">
<li data-role="list-divider">Choose an action</li>
<li>View details</li>
<li>Edit</li>
<li>Disable</li>
<li>Delete</li>
</ul>
</div>
When you append any html into a page after the page's initial load, you need to reapply any of the jquery functions in order for them to work when the event occurs
Example...
if you currently have something like this:
<script type="text/javascript">
$(document).ready(function () {
$('a').on('click', function () {
//something
return false;
});
});
</script>
This will do //something whenever the user clicks on any < a > link.
Now that you are loading the new < a > links in after the document is ready, the code above will not apply to the new code as it was not on the page when the javascript applied the above code.
To fix this, you need to run the function that does the //something again after the new < a > has been loaded.
<script type="text/javascript">
$(document).ready(function () {
somethingFunction();
});
});
//this is where we put the code to apply an event, it is now recallable later on.
function somethingFunction(){
$('a').on('click', function () {
//something
return false;
});
}
</script>
Assuming that you are pulling in the new < a > html via an ajax query, you would need to call the somethingFunction() after the ajax query is successful
EG
$.ajax({
type: "POST",
url: "/action" ,
dataType: 'text',
success: function(data){
$('.popups').html(data);
somethingFunction(); // THIS IS WHERE IT APPLIES THE EVENT TO YOUR NEW HTML.
}
});
If I understood correctly, you want to add buttons dinamically, resulting in the style proposed in your example:
class="ui-btn ui-corner-all ui-shadow ui-btn-inline ui-icon-gear ui-btn-icon-left ui-btn-a"
To apply jQuery Mobile enhancements after appending some HTML you have to call the widget creation method: .button(); in this case (can be .checkboxradio();, .listview();, etc).
I put toghether a JSFiddle which demonstrates dynamically creating a button calling .button() and also applying hardcoded classes (which I think it's not a good thing to do).
There is a demo available in jquery mobile documents Dynamically create popup
Following i write a simple html tags in javascript then append in to jquery mobile pages.
html:
<div data-role="page">
<div data-role="content" id="forpopup">
</div>
<div>
Here is the Fiddle Demo.
i hope this will be helpful.

Execute custom script after page loaded with Ratchet\Push.js

So on the GitHub documentation for Ratchet 2.0.2 I found the following statement.
Script tags containing JavaScript will not be executed on pages that
are loaded with push.js. If you would like to attach event handlers to
elements on other pages, document-level event delegation is a common
solution.
Can someone please spell out exactly how to get a custom <script> to execute after being loaded by Push.js?
On my first page, I have a Table view, with several links to other pages, one of them being a link to a second page with a Twitter Feed widget on it.
<li class="table-view-cell media">
<a class="navigate-right" href="Twitter.php" data-transition="slide-in">
<span class="media-object pull-left icon icon-person"></span>
<div class="media-body">
Twitter Feed
</div>
</a>
</li>
The second page only contains the twitter feed widget code. When I browse to this page directly (without being loaded by Push.js) everything loads correctly, but when it is loaded via Push.js, the script is not executed.
Can someone please explain what I need to do to get this script to execute after being loaded by Push.js? I've searched Google, Stack Exchange, and Github\Ratchet issues and have not been able to find a good example of how to accomplish this.
One solution would be to add data-ignore="push" to the link, but I want to know how to do with WITH push.js.
<div class="content">
<a class="twitter-timeline" href="https://twitter.com/XXXX" data-widget-id="XXXX">Tweets by XXX</a>
</div>
<script>
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
</script>
EDIT: below was how I originally solved this problem, which worked fine, but I came up with a better solution, which I posted as the answer to this question.
I finally figured it out.
On your first page, you need to do the following...
var checkPage = function(){
//Only run if twitter-widget exists on page
if(document.getElementById('twitter-widget')) {
loadTwitterFeed(document,"script","twitter-wjs");
}
};
window.addEventListener('push', checkPage);
checkPage() will execute for every time a new page is loaded via push.
Just made a change for Ratchet.js to make individual js works for each page more elegant.(https://github.com/mazong1123/ratchet-pro)
By using the new ratchetPro.js, we can do followings:
(function () {
var rachetPageManager = new window.RATCHET.Class.PageManager();
rachetPageManager.ready(function () {
// Put your logic here.
});
})();

Initializing Select2 inside of Highslide

I have a corporate web mail service and I use Twitter Bootstrap Modal Window in order to compose and answer emails online. Such a Modal Window contains 2 Select2 elements for TO and CC fields, usual input field for a subject, textarea and Send button.
I was looking for a different type of popup window for that and I decided to use Highslide instead of Modal as with Highslide I can switch focus back to the main page, open more windows with emails in the same time, move the Highslide windows around etc.
So I took my modal content and saved it as a separate html page and I'm getting it with a ajax request but I can't figure out now how to initialize Select2 and other elements as those needs to be initialized at the page load and I renger the Highslide Window later as opposite to Modal Window that was alway present on the page.
Here what was my original index.php whith Modal Window working:
<table id="datatable">
// ajax table with all the emails
</table>
<div id="modal-email" class="modad hide fade">
//here is email form goes...
<label>TO:</label><input id="email-to" />
<label>CC:</label><input id="email-cc" />
<label>Subject:</label><input id="email-subject" />
<textarea id="email-body" />
<button>Send</button>
</div>
$('#email-to').select2({
// initialization parameters
});
$('#email-cc').select2({
// initialization parameters
});
$(document).ready( function() {
$('#datatable').delegate('tr', 'click', function() {
fill_email_values();
$('#modal-email').modal('show');
}
});
So now I took the #modal-email and moved to a separate file
email.form.html:
<label>TO:</label><input id="email-to" />
<label>CC:</label><input id="email-cc" />
<label>Subject:</label><input id="email-subject" />
<textarea id="email-body" />
<button>Send</button>
and I have modified the index.php file into:
<table id="datatable">
// ajax table with all the emails
</table>
<div class="highslide-html-content" id="highslide-form-email">
//form will get inserted here with hs.htmlExapnd command
</div>
$('#email-to').select2({
// initialization parameters
});
$('#email-cc').select2({
// initialization parameters
});
$(document).ready( function() {
$('#datatable').delegate('tr', 'click', function() {
$.ajax ({
type: 'GET',
url: 'email.form.html',
success: function(data) {
return hs.htmlExpand(null, {
contentId: 'highslide-form-email',
maincontentText: data
});
}
});
fill_email_values();
}
});
Obviously when I had Modal Window loading with the index.php page I could initialize all the elements including Select2 but now when I'm loading the email.form.html later only after a click occurs then initial Select2 initialization fails because the elements does not exists yet. However I can't initialize the Select2 later when I put out the popup form as I belive those needs to be initialized on Document Ready or something like and this time has past by. How can I do this?

Embedding a Twitter share button (with JS and everything) into a Mustache template

How can I embed a Twitter (with JS and everything) share button into a Mustache template?
The problem which I have is that my AJAX app does not reload the page, but simply switches views based on Mustache templates. I noticed that functionality provided by widjets.js simply does not get turned on, because the JS files gets loaded only once per application lifetime, and searches for tags decorated with a "twitter" tag on DOM_READY. This however, completely excludes the cases when HTML gets rendered from a template later on.
I know that I can use a raw hyperlink to twitter and customize it to o look like a button, but that is just too primitive.
Here's a solution that worked for me using a template inside my HTML file:
social.js:
$(function() {
var socialFeeds = {
twitter: {
account: "your-twitter-account",
script: function() {
// twitter code goes here, minus the script tags
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
// in my case, I had to re-render the twitter button, see here:
// http://stackoverflow.com/a/6536108/805003
$.ajax({ url: 'http://platform.twitter.com/widgets.js', dataType: 'script', cache:true});
}
}
}
$.Mustache.addFromDom('social-template');
$('#social').mustache('social-template', socialFeeds);
}
index.html:
<script id="social-template" type="text/html">
<div id='social'>
<p>Twitter button:</p>
Tweet
{{ twitter.script }}
</div>
</script>
You could call the init functions not on document ready but from the views where you want the twitter button to appear.

Hide, load, and show div with javascript

I have a few pages from each other to interact with page with id load, as below:
inside process.html
<div id="guest_details"> </div>
<div id="first_start"> </div>
<script>
<! -
$('#guest_details').load('?p=guest_details.html');
$('#first_start').load('?p=first_start.html')
$('#guest_details').hide('slow');
$('#first_start').SlideUp('slow')
->
</Script>
inside guest_details.html
<form action="guest_details.php" <form method="POST" id="guest">
<!-- Some cell here -->
<a onclick="$('#guest').submit();" class="button" id="first_start"> <span> <?php echo $button_submit;?> </span> </a>
</Form>
That I want is when the submit button is clicked then:
data sent to guest_details.php
If the data has been sent then hide < div id="guest_details"> < /div>
showing the show < div id="first_start"> < /div>
but when I make it like the above, that not work, Could someone give a clue how to correct?
Thanks a lot
Looking at your previous question and your tags, I assume you are not much aware of AJAX.
You need to
1.post the form asynchronously (without reloading the page, using AJAX).
2. On successfully sending the data, do the dom manipulations.
I suggest using jquery for doing an AJAX post.
Here is a sample code, using jquery:-
$('#guest_details').load('?p=guest_details.html');
$('#first_start').load('?p=first_start.html')
function ajaxPostForm()
{
$.post('guest_details.php',
function(data) {
//Dom manipulation
$('#guest_details').hide('slow');
$('#first_start').SlideUp('slow')
});
}
And your form html inside guest_details.html needs to be like:-
<form method="POST" id="guest">
<!-- Some cell here -->
<a onclick="ajaxPostForm();" class="button" id="first_start"> <span> <?php echo $button_submit;?> </span> </a>
</Form>
The $.post given above is a very basic AJAX post. You may add further features as give in Jquery Post.
Also if you want to post the entire form, you can refer jQuery Form Plugin
Updates
I think I understood your problem better this time. Inside your update where you say this-
by default guest_details.html is
showing and first_start.html is hiding
referring to the sections as guest_details and first_start would make more sense because guest_details.html may mean the page guest_details.html which you might have opened in another window.
Anyway, I am sure you mean the sections inside the page process.html as you have used jquery .load(). Let's call the first_start.html and guest_details.html as sections first_start and guest_details respectively.
As per your updates do you mean the following:-
Initial state
Section guest_details is shown and first_start is hidden
Cases/Situations
When form inside guest_details section is submitted, then hide the section guest_details and show first_start section.
At this state when guest_details is hidden and first_start is shown, the button on first_start can be clicked and on doing so the guest_details section shows again.
During these states where one section is hidden and another is shown reloading/refreshing the page should preserve the states.
If above is the complete scenario, here is the code:-
<script>
<! -
initiateSections(<?php echo $this->session->data['display_state']; ?>);
//state can have "display_first_start" or "display_guest_details"
function initiateSections(state)
{
$('#guest_details').load('?p=guest_details.html');
$('#first_start').load('?p=first_start.html')
if(state == "display_first_start")
{
displayFirstStart();
}
else
{//If chosen or by default
displayGuestDetails();
}
}
function ajaxPostGuestDetails()
{
$.post('guest_details.php', //In this post request - set $this->session->data['display_state'] = 'display_first_start'; in php
function(data)
{
//Dom manipulation
displayFirstStart();
});
}
function ajaxPostFirstStart()
{
$.post('first_start.php', //In this post request - set $this->session->data['display_state'] = 'display_guest_details';
function(data)
{
//Dom manipulation
displayGuestDetails();
});
}
function displayGuestDetails()
{
$('#first_start').hide('slow');
$('#guest_details').slideUp('slow');
}
function displayFirstStart()
{
$('#guest_details').hide('slow');
$('#first_start').slideUp('slow');
}
->
</Script>
You need to implement ajax to post the data to php
http://api.jquery.com/jQuery.ajax/
use ajax success to do your post success activities.
Once ajax is successful do the HTML manipulations
success: function(data) {
}

Categories