How to auto save when using TinyMCE editor - javascript

I am using tinymce editor to provide rich text formatting and along with that I want to provide the option of autosave. I managed to write a script that does exactly that, but there is one problem. I do not want to call that save function if the window is not the current tab, so that unnecessary save calls are not made.
To over come this I using the $(window).focus() but this does not seem to work because when the tinyMCE editor is in focus (meaning I am typing in it) somehow the window goes out of focus (most probably because tinyMCE editor uses an iFrame) and as a result my periodic update function is not being called.
i would very easily solved this problem if there was a handler .onFocus for the editor but there seems to be none. Can anybody suggest me how can I overcome this problem? My code is given below
/* Function to be called for saving the blog */
function saveBlog(){
var ed = tinymce.activeEditor;
/* Ajax call will be done only when some changes has been made in the editor*/
if (ed.isDirty())
{
ed.save();
var link = $(this).attr("href");
var cur_elem = $(this);
cur_elem.html('saving...');
cur_elem.addClass('unclickable');
$.ajax({
type: "POST",
url: link,
data: $("#blog_form :input[name!='csrfmiddlewaretoken']").serialize(),
dataType: 'json',
success: function(){
cur_elem.html('Save');
cur_elem.removeClass('unclickable');
}
});
}
};
var interval_id;
/* Timer resumes when the window comes back in focus */
$(window).focus(function() {
if (!interval_id)
interval_id = setInterval(saveBlog, 5000);
});
/* Whenever window goes out of focus the timer is cleared */
$(window).blur(function() {
clearInterval(interval_id);
interval_id = 0;
});
/* Starts the auto saving for the first time */
$(document).ready(function(){
interval_id = setInterval(saveBlog, 5000);
});
Can anybody help with this problem, I just need to know when the tinyMCE editor instance is in focus so that I can resume the auto saving periodic function. I can add that in addition to the $(window).focus

Although this post is quite old, I have written a plugin that sends the form data to the specified url every x seconds. I have blogged it here.
In short, the idea is to create an iframe, change the target and action of the form dynamically, and submit the form to stimulate an ajax effect. Once saved, I am putting the form element into its initial state so that if the user wants to save manually he or she will not have any difficulties.
Please note that the plugin I've written is for tinymce4. You'll have to change the source code a bit for older versions.

Did you try the onActivate-handler already?

Related

How can I detect page navigation without reloading?

I have script, what work one time when window loaded, it work on this page, but site use some navigation links what not fully reload page (see this answer for example: Modify the URL without reloading the page). How can I detect that and run my script again?
I have one idea: storing URL (without anchor) in variable and check it periodically with current url, but I think this is bad solution. May be you know better one?
JavaScript or JQuery is possible to use.
Use window.onpopstate or window.onpushstate if u are using pushState or replaceState ( from ur given example).
ex:-
To Navigate Without reload ( you already did this )
// Your code to fetch new URL body and title
// update the DOM then use following code to update URL also (don't use location.href, otherwise the page reloads)
// sorry u already know this because u provided the example ;)
let data = { title : "Current Title",
body : document.body.innerHTML" } // to store current page data
window.history.pushState(data, 0, "newURL");
To detect navigation ( i.e., you wanna do )
window.onpushstate: when above code runs for navigation to a new url and load new content without reload ...
window.onpushstate(function() {
// detects ur navigation
})
window.onpopstate: when you press back button
window.onpopstate(function (e) {
let { data } = e.state;
// data object that u gave in pushState method when u called ur last / latest pushState method...
// use this data to retrieve previous data content and title
let { title, body } = data;
document.title = title;
document.body.innerHTML = body
})
for more detail mdn docs
That's because the new pages are either
1 ) Already at the ready and simply being brought in-sight by jQuery
2 ) Ajax called in.
If you scout for your navigation (the links you click on to go to the other page), you should find click me or so.
If you look for wherever this is is bound (i.e.: $('#navigation a').on("click", function(){});, you can simply wrap your script within a function, and trigger this function together with loading the new page every time. (after it, obviously).
I wish I could be more clear, but you did not provide any code yourself, so I have absolutely no idea of what kind of example I should be giving here.
-- the point: Those page changes are triggered by something in your javascript. Find the trigger that makes the page-change happen, and simply insert myCustomFunction();.
If you want to make your bindings update with a new DOM, you could use this:
function setBindings(){
//removing the old bindings prevents the "click" from triggering twice.
$('a').off("click");
$('a').on("click", function(){
//load page and such here
//Apply script you want to run here
setbindings(); //rerun the function to set the bindings.
});
}
I think you are looking for hashchanges you can listen to this event onhashchange
window.onhashchange = function(e) {
var sublink = window.location.hash.substring(1);
//do your thing here
}
You can also check what updated the url after the hashchange
var sublink = window.location.hash.substring(1);
I think the URL of script is cached,do you used Ajax get method?if it is,please
like this write url "wwww.baidu.com?"+Math.random();if not is ,in the firefox ,you can used pageshow event.

Added data disappear

jQuery Core 3.1.0
Chrome, Firefox
Below is a model of jquery.ajax() success behaviour.
Shortly: I managed to fetch data via AJAX. In this model example the data is represented by "Just something" placeholder. Now I want to add the data to the document.
<script>
var add_date = $("#add_date");
function add_date_ajax(){
$('.frame_date').append("Just something");
debugger; // 1
}
debugger; // 2
add_date.click(add_date_ajax);
</script>
A problem: the data appear and then disappear in half a second.
I placed breakpoints.
When the page is loading, it stops at breakpoint 2. That is correct.
When I click #add_date element, the script stops at breakpoint 1. That is also correct.
But when I click "resume script execution", the script again goes to breakpoint 2. This seem strange to me. As if the page is reloaded. Maybe that is why the added text disappears.
Could you help me cope with the problem?
Added later:
https://jsfiddle.net/mv1yu3zw/1/
It disappears because you are reloading the page. The html
Add date
should be
Add date
To bind all your events, you should use the ready on document.
To avoid the reloading of your page (because of the href of the a tag), you have to call preventDefault or use a button.
You should write your code like this:
$(document).ready(function() {
$("#add_date").on("click", add_date_ajax);
});
function add_date_ajax(event) {
event.preventDefault();
$('.frame_date').append("Just something");
}

getElementById() ? Remembering the last active tab after a submit / refresh

I have a really annoying problem, that I can't solve since a few days of trying and googlin' around.
I have some tabs in my form.
When I am in the third tab (3 / 3) and I hit submit to update my form I always get to the first tab. I want to stay at the active tab.
Here is my jQuery
$(document).ready(function () {
/***** intra - Tabs *****/
$('.intra-tab-content').hide();
$('.intra-tab-content:first').show();
$('.intra-tab').click(function () {
var tabContentId = '#' + $(this).attr('name');
$('.intra-tab').attr('class', 'intra-tab');
$(this).attr('class', 'intra-tab intra-tab-bar-actual-tab');
$('.intra-tab-content').hide();
$(tabContentId).show();
});
});
And here is my HTML
<div class="intra-tab-bar">
<ul>
<li>foo
</li>
<li>bar
</li>
<li>foobar
</li>
</ul>
Would be great if someone could help me..
Thanks in advance
Krtl
After you hit submit, the default behavior of your page is to reload, thus resulting your page to get into initial state (tab 1 selected).
So there are two opportunities:
You can save the selected tab on your server (e.g. in a session) and load it in jQuery's ready callback
Don't let your page use the default behavior, instead calling your custom submit callback function and stop propagation:
$("#submit-form").submit(function () {
var formData = $(this).serialize(); //jQuery function to get the forms values
$.ajax({
url: "url", //forms url
type: "POST/PUT/GET/DELETE", //default: get
data: formData,
success: function(data) {
//success callback
}
});
return false; //stops propagation
});
There are a bunch of ways to tackle this issue. The most elegant way is already suggested by Florian, instead of using the browser submit functionality, define your own submit behaviour using ajax which prevents a page load.
Alternatively:
If you can utilize local storage i.e., you client is a HTML5
based browser, what you can do is set a flag for which tab you would
like to load the page. Clear the flag after it is used.
Send back an extra parameter to the server with the final tab the user was on. This way when you reload you can have the tab id sent back from the server and reload your page. This combined with ajax will allow you to change tabs on the client to specify server errors too!
Though this answer is just for more ways to solve the problem. For something that just works, go for ajax!

Check for page refresh or close with jQuery/javascript

I am looking to check if a page has been refreshed or closed with jQuery or javascript.
What I have currently is I have some database values that I want to delete if the user either navigates away or refreshes the page.
I am using AJAX calls to delete the values.
Right now, I have the following code:
The handler:
window.beforeunload = cleanUp;
The cleanUp() method:
function cleanUp() {
// Check to see if it's an actual page change.
if(myActualLeave) {
$.ajax({
type: "POST",
url: "/api/cleanup",
data: { id: myLocalId },
success: function (data) {
console.log(myLocalId + " got removed from the database.");
}
});
}
// Reset the flag, so it can be checked again.
myActualLeave = true;
}
Where myActualLeave is a flag that I set to false when AJAX calls are made, so they don't trigger the beforeunload handler.
The problem I am running into is that when I click a link on my page, so for instance a link to Google, the window.beforeunload doesn't trigger. I may have a misunderstanding of this, but I have tried using jQuery's $(window).unload(...); and the onbeforeunload trigger as well.
What should I use to call javascript when:
the user refreshes the page,
when the user navigates away from the page, or
when the user closes the page?
Edit: It came up in a comment that I could use a click() jQuery handler to detect navigating away. I should have made it more specific that I don't mean when the user clicks a link only then I want it to proc. I want it to trigger when they change pages in any way. So if the address bar gets typed in, for instance.
You should try "onbeforeunload" :
window.onbeforeunload
But i think you can't put "active" (ajax call) code in this callback function. All you can do is defining a confirm modal window that will be displayed to the user before leaving like :
Are you sure you want to leave because...
So you should do as #Leeish said : put a code in the .on('click') of the link so it can launch the ajax call before sending to another page.
But for the "refresh" or "close" scenario, you can consider marking your database row as "draft" (or whatever) and if not saved when on the next page, delete the draft line.

jQuery dialog - a unique dialog gets duplicated on an ajax site

I have a fully ajaxed website, which uses jQuery's $.get calls to fetch the central content of the website upon header clicks.
One of the "screens" (views, actually, using Zend) has a hidden div which is "dialoged" when a user clicks a certain button. This is what happens to me:
I get to the desired screen, and click the open dialog button.
Dialog opens fine. Closing and reopening works as expected.
I go to another screen (mind you, this is ajax, which simply replaces the main content with new content - the hidden div is inside this content, however, and gets replaced along with the main content)
I come back to the previous screen (still ajaxing), and click the open dialog button again. Now all of a sudden, there are two of those hidden divs, both with the identical ID (I can see that if I do a console.log($("div#hiddenDiv").length); ) and they are both spawned in dialog form - I have them on top of each other.
The dialogs get duplicated for as many times as I redo this. If I go to another screen, come back, and open dialog again - I get 3, etc.
I took a lot of precautions - I empty the memory at every ajax click, setting all variables I have nothing to do with anymore to null. I also take care to replace the entire content, the hidden divs as well, on every new ajax call, i.e. screen-transition. I checked and made sure that the function which summons the dialog isn't called more than once - it simply dupes the dialog upon returning to the screen which contains it by default, and I have no idea why. Mind you - no other element is duped. Only this hidden soon-to-be-dialog div.
Also worth noting is the fact that the duping process never begins until I open the dialog for the first time. From that moment on, every ajax [departure/return/dialog-opening]-scheme dupes the invisible div.
Does anyone have any idea why this is happening?
Edit: Code example:
// This causes the screen change when it detects a hash change
// ... stuff ...
if(window.location.hash){
ajaxData(newhash);
}
// ... stuff ...
// This causes the actual change of on-screen content (i.e. this is the ajax call)
function ajaxData(value) {
// ... stuff ...
$.ajax({
url: "/siteexample/"+value,
type: "GET",
mode: "abort",
dataType: type,
success: function(data){
$("#main_content").html(data); // the hidden div is always inside this "data", so it always gets removed when a new screen loads
loaderdisplay('hide');
// Clean Memory
data = null;
},
data: ({ajax : 'Y'})
});
// ... stuff ....
// And finally, this is the part that summons the dialog
function summonDialog() {
console.log("here"); // this shows up only once, so I know this function is not called multiple times.
var dialogBox = $("div#new_window"); // this is the infamous div
$(dialogBox).dialog({
modal: true,
title: "Some title",
resizable: false,
zIndex: 22000,
width: 800,
buttons: {
"Save": function(){
// some function, ends with:
$(dialogBox).dialog("close"); // destroy doesn't change anything
dialogBox = null;
},
Cancel: function(){
$(this).dialog("close"); // destroy doesn't change anything
dialogBox = null;
}
}
});
}
So the sequence of events is:
1. ajaxData to the location where the div is.
2. ajaxData away from it.
3. ajaxData back, and open dialog, everything fine.
4. ajaxData away from it.
5. ajaxData back and open dialog, duped.
Rinse and repeat, from now on they're getting duped.
Edit2:
I was able to temporarily hack this into a fix with this in the summonDialog function:
var dialogBox = $("div#new_window");
var usableDialog = dialogBox[0];
$(dialogBox).remove();
$(usableDialog).dialog({
// ... dialog code as usual ...
But I don't like the solution much. Marc's explanation makes sense, but since I have many different hidden divs with the potential to become dialogs scattered across many different views, removing each one in such a way would be tedious, since they tend to have different context-appropriate IDs and removing by "ui-dialog-content" class (which all divs get once they're dialog-opened) could produce some issues in other parts of the site, since it's a too general scope.
I believe the div that is the dialog will be attached and hidden on the body. Thus, when you replace the #main_content html, you're not really removing it. I would recommend removing the div and re-enabling the .dialog plugin on each html(data) reload.
Something like this:
success: function(data){
$("#new_window").remove();
$("#main_content").html(data);
loaderdisplay('hide');
summonDialog();
}
And easy way to test this is to simply console.log($("#new_window").length); when you get dupes.
I had exactly the same problem, The dialog was duplicated even after
$('.content').html('');
So I added this:
$("#divEditAdvice").remove();
That was the solution as #Marc mention above.

Categories

Resources