Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F7055601
editor_plugin_src.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
editor_plugin_src.js
View Options
/**
* editor_plugin_src.js
*
* Copyright 2009, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://tinymce.moxiecode.com/license
* Contributing: http://tinymce.moxiecode.com/contributing
*
* Adds auto-save capability to the TinyMCE text editor to rescue content
* inadvertently lost. This plugin was originally developed by Speednet
* and that project can be found here: http://code.google.com/p/tinyautosave/
*
* TECHNOLOGY DISCUSSION:
*
* The plugin attempts to use the most advanced features available in the current browser to save
* as much content as possible. There are a total of four different methods used to autosave the
* content. In order of preference, they are:
*
* 1. localStorage - A new feature of HTML 5, localStorage can store megabytes of data per domain
* on the client computer. Data stored in the localStorage area has no expiration date, so we must
* manage expiring the data ourselves. localStorage is fully supported by IE8, and it is supposed
* to be working in Firefox 3 and Safari 3.2, but in reality is is flaky in those browsers. As
* HTML 5 gets wider support, the AutoSave plugin will use it automatically. In Windows Vista/7,
* localStorage is stored in the following folder:
* C:\Users\[username]\AppData\Local\Microsoft\Internet Explorer\DOMStore\[tempFolder]
*
* 2. sessionStorage - A new feature of HTML 5, sessionStorage works similarly to localStorage,
* except it is designed to expire after a certain amount of time. Because the specification
* around expiration date/time is very loosely-described, it is preferrable to use locaStorage and
* manage the expiration ourselves. sessionStorage has similar storage characteristics to
* localStorage, although it seems to have better support by Firefox 3 at the moment. (That will
* certainly change as Firefox continues getting better at HTML 5 adoption.)
*
* 3. UserData - A very under-exploited feature of Microsoft Internet Explorer, UserData is a
* way to store up to 128K of data per "document", or up to 1MB of data per domain, on the client
* computer. The feature is available for IE 5+, which makes it available for every version of IE
* supported by TinyMCE. The content is persistent across browser restarts and expires on the
* date/time specified, just like a cookie. However, the data is not cleared when the user clears
* cookies on the browser, which makes it well-suited for rescuing autosaved content. UserData,
* like other Microsoft IE browser technologies, is implemented as a behavior attached to a
* specific DOM object, so in this case we attach the behavior to the same DOM element that the
* TinyMCE editor instance is attached to.
*/
(
function
(
tinymce
)
{
// Setup constants to help the compressor to reduce script size
var
PLUGIN_NAME
=
'autosave'
,
RESTORE_DRAFT
=
'restoredraft'
,
TRUE
=
true
,
undefined
,
unloadHandlerAdded
,
Dispatcher
=
tinymce
.
util
.
Dispatcher
;
/**
* This plugin adds auto-save capability to the TinyMCE text editor to rescue content
* inadvertently lost. By using localStorage.
*
* @class tinymce.plugins.AutoSave
*/
tinymce
.
create
(
'tinymce.plugins.AutoSave'
,
{
/**
* Initializes the plugin, this will be executed after the plugin has been created.
* This call is done before the editor instance has finished it's initialization so use the onInit event
* of the editor instance to intercept that event.
*
* @method init
* @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
* @param {string} url Absolute URL to where the plugin is located.
*/
init
:
function
(
ed
,
url
)
{
var
self
=
this
,
settings
=
ed
.
settings
;
self
.
editor
=
ed
;
// Parses the specified time string into a milisecond number 10m, 10s etc.
function
parseTime
(
time
)
{
var
multipels
=
{
s
:
1000
,
m
:
60000
};
time
=
/^(\d+)([ms]?)$/
.
exec
(
''
+
time
);
return
(
time
[
2
]
?
multipels
[
time
[
2
]]
:
1
)
*
parseInt
(
time
);
};
// Default config
tinymce
.
each
({
ask_before_unload
:
TRUE
,
interval
:
'30s'
,
retention
:
'20m'
,
minlength
:
50
},
function
(
value
,
key
)
{
key
=
PLUGIN_NAME
+
'_'
+
key
;
if
(
settings
[
key
]
===
undefined
)
settings
[
key
]
=
value
;
});
// Parse times
settings
.
autosave_interval
=
parseTime
(
settings
.
autosave_interval
);
settings
.
autosave_retention
=
parseTime
(
settings
.
autosave_retention
);
// Register restore button
ed
.
addButton
(
RESTORE_DRAFT
,
{
title
:
PLUGIN_NAME
+
".restore_content"
,
onclick
:
function
()
{
if
(
ed
.
getContent
({
draft
:
true
}).
replace
(
/\s| |<\/?p[^>]*>|<br[^>]*>/gi
,
""
).
length
>
0
)
{
// Show confirm dialog if the editor isn't empty
ed
.
windowManager
.
confirm
(
PLUGIN_NAME
+
".warning_message"
,
function
(
ok
)
{
if
(
ok
)
self
.
restoreDraft
();
}
);
}
else
self
.
restoreDraft
();
}
});
// Enable/disable restoredraft button depending on if there is a draft stored or not
ed
.
onNodeChange
.
add
(
function
()
{
var
controlManager
=
ed
.
controlManager
;
if
(
controlManager
.
get
(
RESTORE_DRAFT
))
controlManager
.
setDisabled
(
RESTORE_DRAFT
,
!
self
.
hasDraft
());
});
ed
.
onInit
.
add
(
function
()
{
// Check if the user added the restore button, then setup auto storage logic
if
(
ed
.
controlManager
.
get
(
RESTORE_DRAFT
))
{
// Setup storage engine
self
.
setupStorage
(
ed
);
// Auto save contents each interval time
setInterval
(
function
()
{
self
.
storeDraft
();
ed
.
nodeChanged
();
},
settings
.
autosave_interval
);
}
});
/**
* This event gets fired when a draft is stored to local storage.
*
* @event onStoreDraft
* @param {tinymce.plugins.AutoSave} sender Plugin instance sending the event.
* @param {Object} draft Draft object containing the HTML contents of the editor.
*/
self
.
onStoreDraft
=
new
Dispatcher
(
self
);
/**
* This event gets fired when a draft is restored from local storage.
*
* @event onStoreDraft
* @param {tinymce.plugins.AutoSave} sender Plugin instance sending the event.
* @param {Object} draft Draft object containing the HTML contents of the editor.
*/
self
.
onRestoreDraft
=
new
Dispatcher
(
self
);
/**
* This event gets fired when a draft removed/expired.
*
* @event onRemoveDraft
* @param {tinymce.plugins.AutoSave} sender Plugin instance sending the event.
* @param {Object} draft Draft object containing the HTML contents of the editor.
*/
self
.
onRemoveDraft
=
new
Dispatcher
(
self
);
// Add ask before unload dialog only add one unload handler
if
(
!
unloadHandlerAdded
)
{
window
.
onbeforeunload
=
tinymce
.
plugins
.
AutoSave
.
_beforeUnloadHandler
;
unloadHandlerAdded
=
TRUE
;
}
},
/**
* Returns information about the plugin as a name/value array.
* The current keys are longname, author, authorurl, infourl and version.
*
* @method getInfo
* @return {Object} Name/value array containing information about the plugin.
*/
getInfo
:
function
()
{
return
{
longname
:
'Auto save'
,
author
:
'Moxiecode Systems AB'
,
authorurl
:
'http://tinymce.moxiecode.com'
,
infourl
:
'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave'
,
version
:
tinymce
.
majorVersion
+
"."
+
tinymce
.
minorVersion
};
},
/**
* Returns an expiration date UTC string.
*
* @method getExpDate
* @return {String} Expiration date UTC string.
*/
getExpDate
:
function
()
{
return
new
Date
(
new
Date
().
getTime
()
+
this
.
editor
.
settings
.
autosave_retention
).
toUTCString
();
},
/**
* This method will setup the storage engine. If the browser has support for it.
*
* @method setupStorage
*/
setupStorage
:
function
(
ed
)
{
var
self
=
this
,
testKey
=
PLUGIN_NAME
+
'_test'
,
testVal
=
"OK"
;
self
.
key
=
PLUGIN_NAME
+
ed
.
id
;
// Loop though each storage engine type until we find one that works
tinymce
.
each
([
function
()
{
// Try HTML5 Local Storage
if
(
localStorage
)
{
localStorage
.
setItem
(
testKey
,
testVal
);
if
(
localStorage
.
getItem
(
testKey
)
===
testVal
)
{
localStorage
.
removeItem
(
testKey
);
return
localStorage
;
}
}
},
function
()
{
// Try HTML5 Session Storage
if
(
sessionStorage
)
{
sessionStorage
.
setItem
(
testKey
,
testVal
);
if
(
sessionStorage
.
getItem
(
testKey
)
===
testVal
)
{
sessionStorage
.
removeItem
(
testKey
);
return
sessionStorage
;
}
}
},
function
()
{
// Try IE userData
if
(
tinymce
.
isIE
)
{
ed
.
getElement
().
style
.
behavior
=
"url('#default#userData')"
;
// Fake localStorage on old IE
return
{
autoExpires
:
TRUE
,
setItem
:
function
(
key
,
value
)
{
var
userDataElement
=
ed
.
getElement
();
userDataElement
.
setAttribute
(
key
,
value
);
userDataElement
.
expires
=
self
.
getExpDate
();
try
{
userDataElement
.
save
(
"TinyMCE"
);
}
catch
(
e
)
{
// Ignore, saving might fail if "Userdata Persistence" is disabled in IE
}
},
getItem
:
function
(
key
)
{
var
userDataElement
=
ed
.
getElement
();
try
{
userDataElement
.
load
(
"TinyMCE"
);
return
userDataElement
.
getAttribute
(
key
);
}
catch
(
e
)
{
// Ignore, loading might fail if "Userdata Persistence" is disabled in IE
return
null
;
}
},
removeItem
:
function
(
key
)
{
ed
.
getElement
().
removeAttribute
(
key
);
}
};
}
},
],
function
(
setup
)
{
// Try executing each function to find a suitable storage engine
try
{
self
.
storage
=
setup
();
if
(
self
.
storage
)
return
false
;
}
catch
(
e
)
{
// Ignore
}
});
},
/**
* This method will store the current contents in the the storage engine.
*
* @method storeDraft
*/
storeDraft
:
function
()
{
var
self
=
this
,
storage
=
self
.
storage
,
editor
=
self
.
editor
,
expires
,
content
;
// Is the contents dirty
if
(
storage
)
{
// If there is no existing key and the contents hasn't been changed since
// it's original value then there is no point in saving a draft
if
(
!
storage
.
getItem
(
self
.
key
)
&&
!
editor
.
isDirty
())
return
;
// Store contents if the contents if longer than the minlength of characters
content
=
editor
.
getContent
({
draft
:
true
});
if
(
content
.
length
>
editor
.
settings
.
autosave_minlength
)
{
expires
=
self
.
getExpDate
();
// Store expiration date if needed IE userData has auto expire built in
if
(
!
self
.
storage
.
autoExpires
)
self
.
storage
.
setItem
(
self
.
key
+
"_expires"
,
expires
);
self
.
storage
.
setItem
(
self
.
key
,
content
);
self
.
onStoreDraft
.
dispatch
(
self
,
{
expires
:
expires
,
content
:
content
});
}
}
},
/**
* This method will restore the contents from the storage engine back to the editor.
*
* @method restoreDraft
*/
restoreDraft
:
function
()
{
var
self
=
this
,
storage
=
self
.
storage
,
content
;
if
(
storage
)
{
content
=
storage
.
getItem
(
self
.
key
);
if
(
content
)
{
self
.
editor
.
setContent
(
content
);
self
.
onRestoreDraft
.
dispatch
(
self
,
{
content
:
content
});
}
}
},
/**
* This method will return true/false if there is a local storage draft available.
*
* @method hasDraft
* @return {boolean} true/false state if there is a local draft.
*/
hasDraft
:
function
()
{
var
self
=
this
,
storage
=
self
.
storage
,
expDate
,
exists
;
if
(
storage
)
{
// Does the item exist at all
exists
=
!!
storage
.
getItem
(
self
.
key
);
if
(
exists
)
{
// Storage needs autoexpire
if
(
!
self
.
storage
.
autoExpires
)
{
expDate
=
new
Date
(
storage
.
getItem
(
self
.
key
+
"_expires"
));
// Contents hasn't expired
if
(
new
Date
().
getTime
()
<
expDate
.
getTime
())
return
TRUE
;
// Remove it if it has
self
.
removeDraft
();
}
else
return
TRUE
;
}
}
return
false
;
},
/**
* Removes the currently stored draft.
*
* @method removeDraft
*/
removeDraft
:
function
()
{
var
self
=
this
,
storage
=
self
.
storage
,
key
=
self
.
key
,
content
;
if
(
storage
)
{
// Get current contents and remove the existing draft
content
=
storage
.
getItem
(
key
);
storage
.
removeItem
(
key
);
storage
.
removeItem
(
key
+
"_expires"
);
// Dispatch remove event if we had any contents
if
(
content
)
{
self
.
onRemoveDraft
.
dispatch
(
self
,
{
content
:
content
});
}
}
},
"static"
:
{
// Internal unload handler will be called before the page is unloaded
_beforeUnloadHandler
:
function
(
e
)
{
var
msg
;
tinymce
.
each
(
tinyMCE
.
editors
,
function
(
ed
)
{
// Store a draft for each editor instance
if
(
ed
.
plugins
.
autosave
)
ed
.
plugins
.
autosave
.
storeDraft
();
// Never ask in fullscreen mode
if
(
ed
.
getParam
(
"fullscreen_is_enabled"
))
return
;
// Setup a return message if the editor is dirty
if
(
!
msg
&&
ed
.
isDirty
()
&&
ed
.
getParam
(
"autosave_ask_before_unload"
))
msg
=
ed
.
getLang
(
"autosave.unload_msg"
);
});
return
msg
;
}
}
});
tinymce
.
PluginManager
.
add
(
'autosave'
,
tinymce
.
plugins
.
AutoSave
);
})(
tinymce
);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jun 12, 3:05 AM (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
861305
Default Alt Text
editor_plugin_src.js (13 KB)
Attached To
Mode
R3 roundcubemail
Attached
Detach File
Event Timeline
Log In to Comment