mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 13:39:01 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			316 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			316 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/*!
 | 
						|
 * jquery.fancytree.edit.js
 | 
						|
 *
 | 
						|
 * Make node titles editable.
 | 
						|
 * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
 | 
						|
 *
 | 
						|
 * Copyright (c) 2008-2017, Martin Wendt (http://wwWendt.de)
 | 
						|
 *
 | 
						|
 * Released under the MIT license
 | 
						|
 * https://github.com/mar10/fancytree/wiki/LicenseInfo
 | 
						|
 *
 | 
						|
 * @version 2.23.0
 | 
						|
 * @date 2017-05-27T20:09:38Z
 | 
						|
 */
 | 
						|
 | 
						|
;(function($, window, document, undefined) {
 | 
						|
 | 
						|
"use strict";
 | 
						|
 | 
						|
 | 
						|
/*******************************************************************************
 | 
						|
 * Private functions and variables
 | 
						|
 */
 | 
						|
 | 
						|
var isMac = /Mac/.test(navigator.platform),
 | 
						|
	escapeHtml = $.ui.fancytree.escapeHtml,
 | 
						|
	unescapeHtml = $.ui.fancytree.unescapeHtml;
 | 
						|
 | 
						|
/**
 | 
						|
 * [ext-edit] Start inline editing of current node title.
 | 
						|
 *
 | 
						|
 * @alias FancytreeNode#editStart
 | 
						|
 * @requires Fancytree
 | 
						|
 */
 | 
						|
$.ui.fancytree._FancytreeNodeClass.prototype.editStart = function(){
 | 
						|
	var $input,
 | 
						|
		node = this,
 | 
						|
		tree = this.tree,
 | 
						|
		local = tree.ext.edit,
 | 
						|
		instOpts = tree.options.edit,
 | 
						|
		$title = $(".fancytree-title", node.span),
 | 
						|
		eventData = {
 | 
						|
			node: node,
 | 
						|
			tree: tree,
 | 
						|
			options: tree.options,
 | 
						|
			isNew: $(node[tree.statusClassPropName]).hasClass("fancytree-edit-new"),
 | 
						|
			orgTitle: node.title,
 | 
						|
			input: null,
 | 
						|
			dirty: false
 | 
						|
			};
 | 
						|
 | 
						|
	// beforeEdit may want to modify the title before editing
 | 
						|
	if( instOpts.beforeEdit.call(node, {type: "beforeEdit"}, eventData) === false ) {
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	$.ui.fancytree.assert(!local.currentNode, "recursive edit");
 | 
						|
	local.currentNode = this;
 | 
						|
	local.eventData = eventData;
 | 
						|
 | 
						|
	// Disable standard Fancytree mouse- and key handling
 | 
						|
	tree.widget._unbind();
 | 
						|
	// #116: ext-dnd prevents the blur event, so we have to catch outer clicks
 | 
						|
	$(document).on("mousedown.fancytree-edit", function(event){
 | 
						|
		if( ! $(event.target).hasClass("fancytree-edit-input") ){
 | 
						|
			node.editEnd(true, event);
 | 
						|
		}
 | 
						|
	});
 | 
						|
 | 
						|
	// Replace node with <input>
 | 
						|
	$input = $("<input />", {
 | 
						|
		"class": "fancytree-edit-input",
 | 
						|
		type: "text",
 | 
						|
		value: tree.options.escapeTitles ? eventData.orgTitle : unescapeHtml(eventData.orgTitle)
 | 
						|
	});
 | 
						|
	local.eventData.input = $input;
 | 
						|
	if ( instOpts.adjustWidthOfs != null ) {
 | 
						|
		$input.width($title.width() + instOpts.adjustWidthOfs);
 | 
						|
	}
 | 
						|
	if ( instOpts.inputCss != null ) {
 | 
						|
		$input.css(instOpts.inputCss);
 | 
						|
	}
 | 
						|
 | 
						|
	$title.html($input);
 | 
						|
 | 
						|
	// Focus <input> and bind keyboard handler
 | 
						|
	$input
 | 
						|
		.focus()
 | 
						|
		.change(function(event){
 | 
						|
			$input.addClass("fancytree-edit-dirty");
 | 
						|
		}).keydown(function(event){
 | 
						|
			switch( event.which ) {
 | 
						|
			case $.ui.keyCode.ESCAPE:
 | 
						|
				node.editEnd(false, event);
 | 
						|
				break;
 | 
						|
			case $.ui.keyCode.ENTER:
 | 
						|
				node.editEnd(true, event);
 | 
						|
				return false; // so we don't start editmode on Mac
 | 
						|
			}
 | 
						|
			event.stopPropagation();
 | 
						|
		}).blur(function(event){
 | 
						|
			return node.editEnd(true, event);
 | 
						|
		});
 | 
						|
 | 
						|
	instOpts.edit.call(node, {type: "edit"}, eventData);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * [ext-edit] Stop inline editing.
 | 
						|
 * @param {Boolean} [applyChanges=false] false: cancel edit, true: save (if modified)
 | 
						|
 * @alias FancytreeNode#editEnd
 | 
						|
 * @requires jquery.fancytree.edit.js
 | 
						|
 */
 | 
						|
$.ui.fancytree._FancytreeNodeClass.prototype.editEnd = function(applyChanges, _event){
 | 
						|
	var newVal,
 | 
						|
		node = this,
 | 
						|
		tree = this.tree,
 | 
						|
		local = tree.ext.edit,
 | 
						|
		eventData = local.eventData,
 | 
						|
		instOpts = tree.options.edit,
 | 
						|
		$title = $(".fancytree-title", node.span),
 | 
						|
		$input = $title.find("input.fancytree-edit-input");
 | 
						|
 | 
						|
	if( instOpts.trim ) {
 | 
						|
		$input.val($.trim($input.val()));
 | 
						|
	}
 | 
						|
	newVal = $input.val();
 | 
						|
 | 
						|
	eventData.dirty = ( newVal !== node.title );
 | 
						|
	eventData.originalEvent = _event;
 | 
						|
 | 
						|
	// Find out, if saving is required
 | 
						|
	if( applyChanges === false ) {
 | 
						|
		// If true/false was passed, honor this (except in rename mode, if unchanged)
 | 
						|
		eventData.save = false;
 | 
						|
	} else if( eventData.isNew ) {
 | 
						|
		// In create mode, we save everyting, except for empty text
 | 
						|
		eventData.save = (newVal !== "");
 | 
						|
	} else {
 | 
						|
		// In rename mode, we save everyting, except for empty or unchanged text
 | 
						|
		eventData.save = eventData.dirty && (newVal !== "");
 | 
						|
	}
 | 
						|
	// Allow to break (keep editor open), modify input, or re-define data.save
 | 
						|
	if( instOpts.beforeClose.call(node, {type: "beforeClose"}, eventData) === false){
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	if( eventData.save && instOpts.save.call(node, {type: "save"}, eventData) === false){
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	$input
 | 
						|
		.removeClass("fancytree-edit-dirty")
 | 
						|
		.off();
 | 
						|
	// Unbind outer-click handler
 | 
						|
	$(document).off(".fancytree-edit");
 | 
						|
 | 
						|
	if( eventData.save ) {
 | 
						|
		// # 171: escape user input (not required if global escaping is on)
 | 
						|
		node.setTitle( tree.options.escapeTitles ? newVal : escapeHtml(newVal) );
 | 
						|
		node.setFocus();
 | 
						|
	}else{
 | 
						|
		if( eventData.isNew ) {
 | 
						|
			node.remove();
 | 
						|
			node = eventData.node = null;
 | 
						|
			local.relatedNode.setFocus();
 | 
						|
		} else {
 | 
						|
			node.renderTitle();
 | 
						|
			node.setFocus();
 | 
						|
		}
 | 
						|
	}
 | 
						|
	local.eventData = null;
 | 
						|
	local.currentNode = null;
 | 
						|
	local.relatedNode = null;
 | 
						|
	// Re-enable mouse and keyboard handling
 | 
						|
	tree.widget._bind();
 | 
						|
	// Set keyboard focus, even if setFocus() claims 'nothing to do'
 | 
						|
	$(tree.$container).focus();
 | 
						|
	eventData.input = null;
 | 
						|
	instOpts.close.call(node, {type: "close"}, eventData);
 | 
						|
	return true;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
* [ext-edit] Create a new child or sibling node and start edit mode.
 | 
						|
*
 | 
						|
* @param {String} [mode='child'] 'before', 'after', or 'child'
 | 
						|
* @param {Object} [init] NodeData (or simple title string)
 | 
						|
* @alias FancytreeNode#editCreateNode
 | 
						|
* @requires jquery.fancytree.edit.js
 | 
						|
* @since 2.4
 | 
						|
*/
 | 
						|
$.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode = function(mode, init){
 | 
						|
	var newNode,
 | 
						|
		tree = this.tree,
 | 
						|
		self = this;
 | 
						|
 | 
						|
	mode = mode || "child";
 | 
						|
	if( init == null ) {
 | 
						|
		init = { title: "" };
 | 
						|
	} else if( typeof init === "string" ) {
 | 
						|
		init = { title: init };
 | 
						|
	} else {
 | 
						|
		$.ui.fancytree.assert($.isPlainObject(init));
 | 
						|
	}
 | 
						|
	// Make sure node is expanded (and loaded) in 'child' mode
 | 
						|
	if( mode === "child" && !this.isExpanded() && this.hasChildren() !== false ) {
 | 
						|
		this.setExpanded().done(function(){
 | 
						|
			self.editCreateNode(mode, init);
 | 
						|
		});
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	newNode = this.addNode(init, mode);
 | 
						|
 | 
						|
	// #644: Don't filter new nodes.
 | 
						|
	newNode.match = true;
 | 
						|
	$(newNode[tree.statusClassPropName])
 | 
						|
		.removeClass("fancytree-hide")
 | 
						|
		.addClass("fancytree-match");
 | 
						|
 | 
						|
	newNode.makeVisible(/*{noAnimation: true}*/).done(function(){
 | 
						|
		$(newNode[tree.statusClassPropName]).addClass("fancytree-edit-new");
 | 
						|
		self.tree.ext.edit.relatedNode = self;
 | 
						|
		newNode.editStart();
 | 
						|
	});
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * [ext-edit] Check if any node in this tree  in edit mode.
 | 
						|
 *
 | 
						|
 * @returns {FancytreeNode | null}
 | 
						|
 * @alias Fancytree#isEditing
 | 
						|
 * @requires jquery.fancytree.edit.js
 | 
						|
 */
 | 
						|
$.ui.fancytree._FancytreeClass.prototype.isEditing = function(){
 | 
						|
	return this.ext.edit ? this.ext.edit.currentNode : null;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * [ext-edit] Check if this node is in edit mode.
 | 
						|
 * @returns {Boolean} true if node is currently beeing edited
 | 
						|
 * @alias FancytreeNode#isEditing
 | 
						|
 * @requires jquery.fancytree.edit.js
 | 
						|
 */
 | 
						|
$.ui.fancytree._FancytreeNodeClass.prototype.isEditing = function(){
 | 
						|
	return this.tree.ext.edit ? this.tree.ext.edit.currentNode === this : false;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*******************************************************************************
 | 
						|
 * Extension code
 | 
						|
 */
 | 
						|
$.ui.fancytree.registerExtension({
 | 
						|
	name: "edit",
 | 
						|
	version: "2.23.0",
 | 
						|
	// Default options for this extension.
 | 
						|
	options: {
 | 
						|
		adjustWidthOfs: 4,   // null: don't adjust input size to content
 | 
						|
		allowEmpty: false,   // Prevent empty input
 | 
						|
		inputCss: {minWidth: "3em"},
 | 
						|
		// triggerCancel: ["esc", "tab", "click"],
 | 
						|
		// triggerStart: ["f2", "dblclick", "shift+click", "mac+enter"],
 | 
						|
		triggerStart: ["f2", "shift+click", "mac+enter"],
 | 
						|
		trim: true,          // Trim whitespace before save
 | 
						|
		// Events:
 | 
						|
		beforeClose: $.noop, // Return false to prevent cancel/save (data.input is available)
 | 
						|
		beforeEdit: $.noop,  // Return false to prevent edit mode
 | 
						|
		close: $.noop,       // Editor was removed
 | 
						|
		edit: $.noop,        // Editor was opened (available as data.input)
 | 
						|
//		keypress: $.noop,    // Not yet implemented
 | 
						|
		save: $.noop         // Save data.input.val() or return false to keep editor open
 | 
						|
	},
 | 
						|
	// Local attributes
 | 
						|
	currentNode: null,
 | 
						|
 | 
						|
	treeInit: function(ctx){
 | 
						|
		this._superApply(arguments);
 | 
						|
		this.$container.addClass("fancytree-ext-edit");
 | 
						|
	},
 | 
						|
	nodeClick: function(ctx) {
 | 
						|
		if( $.inArray("shift+click", ctx.options.edit.triggerStart) >= 0 ){
 | 
						|
			if( ctx.originalEvent.shiftKey ){
 | 
						|
				ctx.node.editStart();
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return this._superApply(arguments);
 | 
						|
	},
 | 
						|
	nodeDblclick: function(ctx) {
 | 
						|
		if( $.inArray("dblclick", ctx.options.edit.triggerStart) >= 0 ){
 | 
						|
			ctx.node.editStart();
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		return this._superApply(arguments);
 | 
						|
	},
 | 
						|
	nodeKeydown: function(ctx) {
 | 
						|
		switch( ctx.originalEvent.which ) {
 | 
						|
		case 113: // [F2]
 | 
						|
			if( $.inArray("f2", ctx.options.edit.triggerStart) >= 0 ){
 | 
						|
				ctx.node.editStart();
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
		case $.ui.keyCode.ENTER:
 | 
						|
			if( $.inArray("mac+enter", ctx.options.edit.triggerStart) >= 0 && isMac ){
 | 
						|
				ctx.node.editStart();
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		return this._superApply(arguments);
 | 
						|
	}
 | 
						|
});
 | 
						|
}(jQuery, window, document));
 |