-
Szymon Olewniczak authoredSzymon Olewniczak authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
edit.js 7.29 KiB
/**
* Functions for text editing (toolbar stuff)
*
* @todo most of the stuff in here should be revamped and then moved to toolbar.js
* @author Andreas Gohr <andi@splitbrain.org>
*/
/**
* Creates a toolbar button through the DOM
*
* Style the buttons through the toolbutton class
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Michal Rezler <m.rezler@centrum.cz>
*/
function createToolButton(icon,label,key,id,classname){
var $btn = jQuery(document.createElement('button')),
$ico = jQuery(document.createElement('img'));
// prepare the basic button stuff
$btn.addClass('toolbutton');
if(classname){
$btn.addClass(classname);
}
$btn.attr('title', label).attr('aria-controls', 'wiki__text');
if(key){
$btn.attr('title', label + ' ['+key.toUpperCase()+']')
.attr('accessKey', key);
}
// set IDs if given
if(id){
$btn.attr('id', id);
$ico.attr('id', id+'_ico');
}
// create the icon and add it to the button
if(icon.substr(0,1) !== '/'){
icon = DOKU_BASE + 'lib/images/toolbar/' + icon;
}
$ico.attr('src', icon);
$ico.attr('alt', '');
$ico.attr('width', 16);
$ico.attr('height', 16);
$btn.append($ico);
// we have to return a DOM object (for compatibility reasons)
return $btn[0];
}
/**
* Creates a picker window for inserting text
*
* The given list can be an associative array with text,icon pairs
* or a simple list of text. Style the picker window through the picker
* class or the picker buttons with the pickerbutton class. Picker
* windows are appended to the body and created invisible.
*
* @param string id the ID to assign to the picker
* @param array props the properties for the picker
* @param string edid the ID of the textarea
* @rteurn DOMobject the created picker
* @author Andreas Gohr <andi@splitbrain.org>
*/
function createPicker(id,props,edid){
// create the wrapping div
var $picker = jQuery(document.createElement('div'));
$picker.addClass('picker a11y');
if(props['class']){
$picker.addClass(props['class']);
}
$picker.attr('id', id).css('position', 'absolute');
function $makebutton(title) {
var $btn = jQuery(document.createElement('button'))
.addClass('pickerbutton').attr('title', title)
.attr('aria-controls', edid)
.bind('click', bind(pickerInsert, title, edid))
.appendTo($picker);
return $btn;
}
jQuery.each(props.list, function (key, item) {
if (!props.list.hasOwnProperty(key)) {
return;
}
if(isNaN(key)){
// associative array -> treat as text => image pairs
if (item.substr(0,1) !== '/') {
item = DOKU_BASE+'lib/images/'+props.icobase+'/'+item;
}
jQuery(document.createElement('img'))
.attr('src', item)
.attr('alt', '')
.appendTo($makebutton(key));
}else if (typeof item == 'string'){
// a list of text -> treat as text picker
$makebutton(item).text(item);
}else{
// a list of lists -> treat it as subtoolbar
initToolbar($picker,edid,props.list);
return false; // all buttons handled already
}
});
jQuery('body').append($picker);
// we have to return a DOM object (for compatibility reasons)
return $picker[0];
}
/**
* Called by picker buttons to insert Text and close the picker again
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function pickerInsert(text,edid){
insertAtCarret(edid,text);
pickerClose();
}
/**
* Add button action for signature button
*
* @param DOMElement btn Button element to add the action to
* @param array props Associative array of button properties
* @param string edid ID of the editor textarea
* @return boolean If button should be appended
* @author Gabriel Birke <birke@d-scribe.de>
*/
function addBtnActionSignature($btn, props, edid) {
if(typeof SIG != 'undefined' && SIG != ''){
$btn.bind('click', function (e) {
insertAtCarret(edid,SIG);
e.preventDefault();
});
return edid;
}
return '';
}
/**
* Determine the current section level while editing
*
* @author Andreas Gohr <gohr@cosmocode.de>
*/
function currentHeadlineLevel(textboxId){
var field = jQuery('#' + textboxId)[0],
s = false,
opts = [field.value.substr(0,DWgetSelection(field).start)];
if (field.form.prefix) {
// we need to look in prefix context
opts.push(field.form.prefix.value);
}
jQuery.each(opts, function (_, opt) {
// Check whether there is a headline in the given string
var str = "\n" + opt,
lasthl = str.lastIndexOf("\n==");
if (lasthl !== -1) {
s = str.substr(lasthl+1,6);
return false;
}
});
if (s === false) {
return 0;
}
return 7 - s.match(/^={2,6}/)[0].length;
}
/**
* global var used for not saved yet warning
*/
window.textChanged = false;
/**
* Delete the draft before leaving the page
*/
function deleteDraft() {
if (is_opera || window.keepDraft) {
return;
}
var $dwform = jQuery('#dw__editform');
if($dwform.length === 0) {
return;
}
// remove a possibly saved draft using ajax
jQuery.post(DOKU_BASE + 'lib/exe/ajax.php',
{
call: 'draftdel',
id: $dwform.find('input[name=id]').val()
}
);
}
/**
* Activate "not saved" dialog, add draft deletion to page unload,
* add handlers to monitor changes
*
* Sets focus to the editbox as well
*/
jQuery(function () {
var $editform = jQuery('#dw__editform');
if ($editform.length == 0) {
return;
}
var $edit_text = jQuery('#wiki__text');
if ($edit_text.length > 0) {
if($edit_text.attr('readOnly')) {
return;
}
// set focus and place cursor at the start
var sel = DWgetSelection($edit_text[0]);
sel.start = 0;
sel.end = 0;
DWsetSelection(sel);
$edit_text.focus();
}
var checkfunc = function() {
textChanged = true; //global var
summaryCheck();
};
$editform.change(checkfunc);
$editform.keydown(checkfunc);
window.onbeforeunload = function(){
if(window.textChanged) {
return LANG.notsavedyet;
}
};
window.onunload = deleteDraft;
// reset change memory var on submit
jQuery('#edbtn__save').click(
function() {
window.onbeforeunload = '';
textChanged = false;
}
);
jQuery('#edbtn__preview').click(
function() {
window.onbeforeunload = '';
textChanged = false;
window.keepDraft = true; // needed to keep draft on page unload
}
);
var $summary = jQuery('#edit__summary');
$summary.change(summaryCheck);
$summary.keyup(summaryCheck);
if (textChanged) summaryCheck();
});
/**
* Checks if a summary was entered - if not the style is changed
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function summaryCheck(){
var $sum = jQuery('#edit__summary'),
missing = $sum.val() === '';
$sum.toggleClass('missing', missing).toggleClass('edit', !missing);
}