Dynamically updating contents of div element takes two or three tries - javascript

I'm trying to update the contents of a div, but it's not always working. I'm not sure if it's relevant to my problem, but I am using jquery mobile.
Background:
I have a select menu, which is used to choose a location. I also have a button which is used to get information about the chosen location. Ajax is used to fetch the data, which is shown within a div element on my page. I've found that I need to click the button twice for the div element to update. Oddly, if I add an alert just before I update the div it works fine (i.e. I only need to push the button once).
Code:
$( function() {
$("#weather_submit").click(function(){
$.mobile.pageLoading();
var formData = $("#getWeatherForm").serialize();
$.ajax({
type: "POST",
url: "weather.php",
cache: false,
data: formData,
success: onSuccessWeather,
error: onError
});
return false;
});
});
function onError(data, status) {
$.mobile.pageLoading( true );
alert('error');
}
function onSuccessWeather(data, status) {
$.mobile.pageLoading( true );
//alert(data); // if I use this line of code I never have a problem (i.e. the weatherSummary div updates appropriately
data = $.trim(data);
$("#weatherSummary").html(data);
}
I initially found this problem using my Android EVO, but I've just tried firefox and it happens with that too.
I suspect it's something to do with the .html() not doing its job properly for some reason.
Any ideas?
Thanks!

Try:
$("#page_id_name").page();
But also I think there is a new method in the Beta 2 update:
http://jquerymobile.com/blog/2011/08/03/jquery-mobile-beta-2-released/
New “create” event: Easily enhance all widgets at once
While the page plugin no longer calls each plugin specifically, it
does dispatch a “pagecreate” event, which most widgets use to
auto-initialize themselves. As long as a widget plugin script is
referenced, it will automatically enhance any instances of the widgets
it finds on the page, just like before. For example, if the selectmenu
plugin is loaded, it will enhance any selects it finds within a newly
created page.
This structure now allows us to add a new create event that can be
triggered on any element, saving you the task of manually initializing
each plugin contained in that element. Until now, if a developer
loaded in content via Ajax or dynamically generated markup, they
needed to manually initialize all contained plugins (listview button,
select, etc.) to enhance the widgets in the markup.
Now, our handy create event will initialize all the necessary plugins
within that markup, just like how the page creation enhancement
process works. If you were to use Ajax to load in a block of HTML
markup (say a login form), you can trigger create to automatically
transform all the widgets it contains (inputs and buttons in this
case) into the enhanced versions. The code for this scenario would be:
$( ...new markup that contains widgets... ).appendTo( ".ui-page" ).trigger( "create" );
So if you update to Beta 2 try something like this (untested):
$("#weatherSummary").html(data).trigger( "create" );

Related

Is it possible to return content from a custom window in TinyMCE 4?

Like many others, due to the limitations of TinyMCE's Image Plugin, I've decided to take the route of creating one that ties into my site's own uploading system.
I've gotten this partially working and pulling up a individual page, designed just for the purpose. However, now I want to return content from selecting images on this page. Is that possible or am I hitting a dead end?
tinymce.PluginManager.add('imageLoader', function(editor, url) {
// Adds a menu item to the tools menu
editor.addButton('imageLoader', {
icon: 'mce-ico mce-i-link',
image: 'Photos.png',
onclick: function() {
// Open window
editor.windowManager.open({
title: 'Image Loader',
url: 'load_images',
width: 500,
height: 400,
onsubmit: function(e) {
// Insert content when the window form is submitted
editor.insertContent('Image To Insert');
}
});
}
});
return {
getMetadata: function () {
return {
name: "Image Loader"
};
}
};
});
We made this a lot easier in TinyMCE 5 with a new URL dialog api:
https://www.tiny.cloud/docs/ui-components/urldialog/
In version 4, I believe the usual technique was to (inside the iframe) access the TinyMCE instance that opened the dialog via window.parent.tinymce.activeEditor, and then replicate the onsubmit function there. With the editor instance you can insert whatever content you need to and then editor.windowManager.close() will close the topmost window (i.e. the url dialog).
For more advanced use cases, editor.windowManager.getParams() can be used to pass information between the plugin and dialog, although perhaps not from the dialog to the plugin. editor.plugins is another possible technique, it's a name/value object of active plugin instances (it's a live reference to the return value from the PluginManager.add init function which can be mutated at runtime).
These are all fairly complicated, but likely more reliable than searching for the dialog iframe from your plugin.
I found an answer, although this is likely not the most elegant solution.
The image that I'm selecting is passed into a hidden text input in my custom page. From there, on Submit or Closing the TinyMCE 4 Frame, I use this snippet:
let getVal = $('[role="application"]').find('iframe')[1].contentWindow.document.getElementById("imgHolder").value;
In order:
It first finds the iFrame. Since both external pages and the editor itself use iFrames, this will generally be the 'second' iFrame - unfortunately, it isn't given an ID.
"contentWindow.document.getElementByID" fetches the hidden input, in my case named "imgHolder"
From here, you can get your content as normal with .value, and insert it into the TinyMCE Editor.
I hope this helps point others in the right direction, especially knowing that it gets asked a lot for TinyMCE 4. Further I hope this can be made a bit more elegent as well.

JavaScript stops working after I load another page

I am new to JavaScript and trying to see why my on event listeners are not working. I have found similar posts on stackoverflow however the solutions are not working for me.
var search = function( event ) {
alert("bobo")
$.get("http://localhost:3000/search", {"search" : $("#Search-Bar").val()}, function(data, status){
if(status == "success")
$(".centering.text-center").html(data)
})
}
var attachListeners = function(){
$("#Search").on("click", search)
$("#SearchIcon").click( () => search() )
$("#Search-Bar").keypress( event => (event.KeyCode == 13 || event.which == 13) ? search() : undefined )
}
$(document).ready( function(){
attachListeners()
})
My website is not a single page application. I have attached the listeners to my navigation search bar where I load a different view through the nav links and my server(ruby back end) uploads a new html page.
On the first load I have noticed that document ready gets called and everything else works. The on and click. After I use my navigation and load a different html page my events disappear. In my html views my searchbar, searchicon, and a search text have consistent id's through out. I have tried using window.load() and putting an onload attribute for my body <body onload=attachListeners()> but neither worked(perhaps I didn't use them properly). I also noticed that when I render the next html views my docment.ready does not get called. However, if I forcefully refresh the page with an F5 the listeners are active again for that one html page. What am I missing here that I don't understand?
It looks like you might be using Turbolinks, from the Readme for the project:
When you follow a link, Turbolinks automatically fetches the page, swaps in its <body>, and merges its <head>, all without incurring the cost of a full page load.
Since this library makes it so the page ever only loads once, normal javascript window.onload, DOMContentLoaded, and jQuery ready events don't function after the initial page load and you have to use
document.addEventListener("turbolinks:load", function() {
instead of those. If you're new to turbo links, I suggest reading through that README to see what it's all about.
I've never understood why the Rails team would put something like this in rails and enable it by default, and in every single project I've made since they made that change the first thing I do is uninstall it, and when I forgot to do so, I spend several hours later in the project wondering why my javascript is broken.

jQuery: Reload a DIV which was already loaded by AJAX (without url)?

I load a div by a simple
$('#thediv').load("theurl/param1/param2/param3");
The params differ - and I grab them from different points - depends on where the user clicks. (Different filter options..)
Now I'm searching for a simple way to reload this content with the url it was actually loaded - to avoid searching for the right filter params at this place. It is possible?
jQuery will not "save" the source of information on its own, but it is possible to specify it manually using the .data() method alongside the initial .ajax()
This means during the initial load, you can associate a URL with a div by saying something like .data("source-url","MY URL GOES HERE")
After that, you can look up that information the next time you want to reload it by using .data("source-url")
For Example:
function reloadDivs() {
// Look up all of the divs that we might want to reload
$("div.reloadable").each(function(i,el) {
// For each div, check to see if the source-url was set
// If it was set, re-run the ajax call
var $el = $(el);
if($el.data("source-url")
$el.load($el.data("source-url"));
});
}
$(function() {
// Set the initial source, change mypage.html to your actual source
$("#example-div").data("source-url","mypage.html");
$("#refreshbutton").click(reloadDivs);
});
Hope this helps!

Duplicate javascripts are getting loaded ajax

I'm developing a web based document management for my final year project. The user interacts with only one page and the respective pages will be called using AJAX when the user click the respective tabs (Used tabs for navigation).
Due to multiple user levels (admin, managers, etc.) I've put the javascripts into the correspondent web pages.
When user requests the user request everythings work perfectly except some situations where some functions are triggered multiple times. I found the problem. It is each time the user clicks a tab it loads same scripts as new instance and both of them will be triggered when I call a function.
to load the content I tired
.load and $.ajax(); non of them address the issue.
I tried to put all into the main page at that time my jQueryUI does not work. I tired
$(document).load('click', $('#tab_root li'), function(){});
Same issue remain.
Can anyone help me out this issue?
--Edit--
$(function){
$(document).on('click','#tabs',function(e){
getAjax($(this))
});
}
//method to load via AJAX
function getAjax(lst){
var cont = $(lst).text();
$.ajax({
url:'../MainPageAjaxSupport',
data: {
"cont":cont
},
error: function(request, status, error){
if(status==404){
$('#ajax_body').html("The requested page is not found. Please try again shortly");
}
},
success: function(data){
$('#ajax_body').html(data);
},
});
}
You can't undo JavaScript after it has been executed by simply unloading the file or removing the script element.
The best solution would probably be to set a variable in each JavaScript file you include in your ajax data and include them from an online inline JavaScript inside the ajax data along with a conditional like such:
<script>
if(!tab1Var) $.getScript("filename");
<script>
Older Solutions
You can manually unbind each event before setting them with off.
$(function){
$('#tabs').off('click');
$('#tabs').on('click',function(e){
getAjax($(this));
});
}
Alternatively you can initialize a global variable (eventsBound1=false) for each tab in the main html:
$(function){
if(!eventsBound1){
$('#tabs').on('click', function(e){
getAjax($(this));
});
eventsBound1 = true;
}
}
The tabs click event is only an example you have to do this for each time you bind an event in the scripts that are being reloaded.
if all the events are bound to things inside ajax_body, a final thing you can try is:
success: function(data){
$('#ajax_body').empty();
$('#ajax_body').html(data);
},
You have bind an event click on 'document' so getAjax() only replace the '#ajax_body' not the 'document'.
This means old event is still attached to the 'document' all you need is to unbind event by using $(document).off('click'); or change 'document' to other elements.

jQuery replace all HTML

I'm trying to replace all the HTML (including the HTML tags) with another page. What I'm trying to do is having a website acting as an app even when navigating the another page.
Here is the code :
(function($) {
Drupal.behaviors.loadingPage = {
attach: function(context,settings) {
$('a').click(function(event) {
event.preventDefault();
// Create the loading icon
// ...
$.ajax({
url: $(this).attr('href'),
success: function(data) {
$('html').replaceWith(data);
}
});
});
}
};
})(jQuery);
I've tried several things. replaceWith() causes a jQuery error in jquery.js after deleting the HTML tag, I guess it is because it can't find the parent anymore to add the replacement.
The best result I got was with document.write(data). The problem is, the javascript code on the loaded page is not executed.
Anyone got a better idea ?
A better idea? Yeah, just load the new page normally by setting window.location instead of using AJAX. Or submit a form.
Otherwise, if you want to load something to replace all of the visible content of the current page but keep the current page's script going, put all the visible content in a frame sized to fill the browser window - which, again, you wouldn't populate using AJAX.
(I like AJAX, but I don't see why you'd use it to replace a whole page.)

Categories