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.
Related
I have a div which is populated by ajax. When done this way the datepicker is not called. I originally had the datepicker loaded in the header of the containing page but have tgried loading it within the script which calls the div content but again no luck. The Jquery library is called in the header of the main page. If I load the pages without ajax then there is no problem and the datepicker works fine.
<li><a data-target="#halloffame" href="abscencerecords.php">Absence Records</a></li>
<li><a data-target="#halloffame" href="abscencerequestform.php">Absence Request</a></li>
<li><a data-target="#halloffame" href="personaldetails.php">Personal Details</a></li>
<?php endif ?>
<?php endif ?>
</ul></div>
<div class="clear padding20"></div>
<div id="halloffame" class="bordered_box"></div>
<script>
$('[data-target]').click( function (e) {
$(document).ready(function() { $("#datepicker").datepicker({ dateFormat: 'dd/mm/yy' }); });
$(document).ready(function() { $(".datepickermultiple").multiDatesPicker({ dateFormat: 'dd/mm/yy' }); });
var target = $($(this).attr('data-target'));
target.load($(this).attr('href'));
e.preventDefault(); // prevent anchor from changing window.location
});
</script>
Most plugins only initialize for elements that exist ... at the time the code is run
In order to initialize a plugin within ajax loaded content you need to do that within the completion callback of ajax.
Try changing :
target.load($(this).attr('href'));
To
target.load($(this).attr('href'), function(){
// new html now exists , initialize plugins or event handlers or dom manipulation here
$(this).find(selector).somePlugin()
});
Reference load() docs
In my case datepicker plugin was getting initialize, but the issue was position of datepicker calendar, I solved it by adding below CSS to the page:
#ui-datepicker-div {
position: absolute !important;;
}
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 });
});
HTML
<div id="add_to_library" class="add-library-wrapper">
<a href="javascript:void(0)" class="library-select" id="library-status-select" >Click</a>
<div class="dropdown">
<ul>
<li><a onclick="create_library_entry('Complete', 123, 124);" href="javascript:void(0)">Stuff</a></li>
</ul>
</div>
jQuery
$('#library-status-select').click(function() {
$(this).toggleClass('open');
$('.dropdown').toggleClass('open');
});
function create_library_entry(status, user_id, anime_id) {
jQuery('#custom_lightbox').html('');
jQuery.post("/wp-content/themes/phanime/custom_functions/create_single_libraryEntry.php", {user_id : user_id, anime_id : anime_id, status : status}, function(data) {
//this is your response data from serv
console.log(data);
jQuery('#add_to_library').html(data);
});
}
So when I click on the anchor tag with the id of library-status-select it shows the div with the class dropdown. By adding an open class and so on. Once the dropdown shows it also has a link that does a jQuery post. The jQuery post returns it's result which in the #add_to_library id, where the link is contained. That link is replaced by another link that is returned from that jQuery.post. That link looks like this...
<a href="javascript:void(0)" class="library-select" id="library-status-select" >Click me updated</a>
It's essentially the same link with the same class / id but for some reason the jQuery.addClass / removeClass no longer works on the link that is returned from the jQuery.post. In other words the open class is not being added. If anyone knows exactly why this happens, it would be of great help.
Since you are replacing the contests you are dealing with dynamic contents so use event delegation
$('#add_to_library').on('click', '#library-status-select', function () {
$(this).toggleClass('open');
$('.dropdown').toggleClass('open');
});
sample.html Code
<ul id="browser" class="filetree">
<li><span class="folder">Folder 1</span>
<ul>
<li><span class="file">Item 1.1</span></li>
</ul>
</li>
</ul>
Main Page Code
<div id="LtrLeftContent">
<script type="text/javascript">
$('#LtrLeftContent').load('sample.html');
</script>
</div>
Page Loaded successfully. But unable to populate Jquery Treeview using bellow code within Main Page
Process 1:
$("div#LtrLeftContent").contents().find("ul#browser").treeview();
Process 2:
$("div#LtrLeftContent").ready(function () {
$("ul#browser.filetree").treeview();
});
Process 3:
$(document).ready(function () {
$("ul#browser").treeview();
});
Process 4:
$("#LtrLeftContent").html().find("#browser").treeview();
But if I put bellow code into "sample.html". the code populate the Treeview successfully
$(document).ready(function () {
$("#browser").treeview();
});
How to set treeview into Main Page in order to populate JQuery treeview ?
Note: I don't want put Javascript into "Sample.html".
You'll need to wait with populating the treeview for sample.html to load (see docs for load):
$('#LtrLeftContent').load('sample.html', function(response, status, xhr) {
$("#browser").treeview();
});
In jQuery mobile, I am trying to detect a successful page change to a specific page. I have the following code, inline on the page I want to load.
<script>
$(document).bind( "pagebeforechange", function( e, data ) {
alert("pagebeforechange");
});
$(document).bind( "pagechange", function( e, data ) {
alert("pagechange");
});
$(document).bind( "pagechangefailed", function( e, data ) {
alert("pagechangefailed");
});
$(document).live( "pagebeforechange", function( e, data ) {
alert("pagebeforechange live");
});
$(document).live( "pagechange", function( e, data ) {
alert("pagechange live");
});
$(document).live( "pagechangefailed", function( e, data ) {
alert("pagechangefailed live");
});
</script>
I get the the appropriate alerts when loading the page directly, or refreshing, but not when navigating from another area in the Jquery Mobile app.
Page is called by the the "Your Car" Tab in the footer
<div id="footer" data-role="footer" data-position="fixed">
<div data-role="navbar">
<ul>
<li>Home</li>
<li>Features</li>
<li>Your Car</li>
<li>Contact</li>
</ul>
</div>
</div>
Would it work to place your code in the pageshow event? It may if you are trying to detect the page or location. Something like this maybe:
<script type="text/javascript">
$('[data-role=page]').live('pageshow', function (event, ui) {
hash = location.hash;
page = hash.susbtr(1);
if (page.indexOf('about.html') >= 0) {
alert('you made it!');
}
});
</script>
UPDATE
After testing this scenario a bit more and rereading your question, I think I was able to reproduce the results.
This works as you described and only fires alerts when loading the page directly or refreshing the page:
<body>
<div data-role="page">
<!-- page stuff -->
</div>
<script type="text/javascript"> ..bind events... </script>
</body>
However, when I move the javascript directly inside the page, it works as expected and fires all of the bound events, no matter how the page was reached:
<body>
<div data-role="page">
<script type="text/javascript"> ..bind events... </script>
<!-- page stuff -->
</div>
</body>
Where are you binding to this events?
Have you read following in the Docs http://code.jquery.com/mobile/latest/demos/docs/api/events.html:
Important: Use pageInit(), not $(document).ready()
The first thing you learn in jQuery is to call code inside the
$(document).ready() function so everything will execute as soon as the
DOM is loaded. However, in jQuery Mobile, Ajax is used to load the
contents of each page into the DOM as you navigate, and the DOM ready
handler only executes for the first page. To execute code whenever a
new page is loaded and created, you can bind to the pageinit event.
This event is explained in detail at the bottom of this page.
Luke's thinking is in the right direction: clearly the problem you had has to do with where in the code the binding is occurring. This is proved by shanabus.
However, in your case, you should be doing the binding when jQuery mobile's mobileinit event is fired, not pageInit, as Luke is suggesting.
Example (fires on all page change events):
<script type="text/javascript">
$(document).bind('mobileinit', function() {
$(document).on('pagechange', function () {
window.alert('page changed!');
});
});
</script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.js"></script>
As illustrated in the code above, be mindful that handlers triggered by mobileinit must be included before the jQuery mobile <script> tag.