kvasilov48
4/8/2015 - 7:31 AM

EditableDomElements

EditableDomElements

function EditableDomElements($container, selector, config) {
	var defaultOpts = {
		textCancel: "Відміна",
		textSave: "Зберегти",
		textNoText: null,
		inputType: 'textarea', // textarea|input
		extractTextFromView: function($view) { return $view.text().trim() },
		setTextToView: function($view, text) { $view.empty().text(text) },
		configureTextarea: function($editor, $view) { $editor.height($view.outerHeight()) },
		placeEditor: function($editor, $view) { $editor.insertAfter($view) },
		domBtnCancel: function(textCancel) { return $("<button>").addClass('btn btn-mini').prop('type', 'button').text(textCancel + " (Esc)") },
		domBtnSave: function(textSave) { return $("<button>").addClass('btn btn-mini').prop('type', 'button').text(textSave + " (Ctrl+Enter)").css('margin-left', '4px') },
		domEditor: function($textarea, $btnCancel, $btnSave) {
			return $div().addClass('inlineEditor').append(
				$textarea,
				$div().append(	$btnCancel, $btnSave ) // buttons
			)
		},
		// Should return {status: OK, text: "saved text"} if submission was successful, otherwise {status: "error_message"}
		submit: function(text, $view, done) {
			alert('submit option of EditableDomElements was not configured!')
			done( { status: "OK", text: text } )
		},
		showSubmissionError: function(message) { alert(message) }
	}
	var opts = $.extend({}, defaultOpts, config)

	function startEditor($view) {
		var text = opts.extractTextFromView($view)
		if (opts.textNoText != null && text == opts.textNoText)
			text = ''

		var inputType = opts.inputType || 'textarea'
		if (inputType != 'textarea' && inputType != 'input')
			inputType = 'textarea'
		var $t = $("<"+inputType+">").val(text)
		opts.configureTextarea($t, $view)

		var $btnCancel = opts.domBtnCancel(opts.textCancel)
		var $btnSave = opts.domBtnSave(opts.textSave)
		var $editor = opts.domEditor($t, $btnCancel, $btnSave)
		var $actionControls = $([]).add($editor).add($btnCancel).add($btnSave)

		opts.placeEditor($editor, $view)
		$view.hide()
		$t.focus()

		function hideEditor() {
			$editor.remove()
			$view.show()
		}

		function showSubmissionError(text) {
			$actionControls.removeAttr('disabled')
			opts.showSubmissionError(text)
		}

		function submitEditor() {
			$actionControls.attr('disabled', 'disabled')
			opts.submit($t.val(), $view, function(res){
				if (typeof res != "object" || !res.status)
					showSubmissionError('Submission result does not contain "status" property')
				else if (res.status != "OK")
					showSubmissionError(res.status)
				else if (typeof res.text == "undefined")
					showSubmissionError('Submission result does not contain "text" property')
				else {
					var textForView = res.text
					if (opts.textNoText != null && textForView == '')
						textForView = opts.textNoText

					opts.setTextToView($view, textForView)
					hideEditor()
					$view.show()
				}
			})
		}

		$btnCancel.click(function(ev){ hideEditor() })
		$btnSave.click(function(ev) { submitEditor() })
		$t.keydown(function(e){
			if (e.keyCode == 27) hideEditor()   // esc
			if (e.ctrlKey && e.keyCode == 13) { submitEditor() } // ctrl+enter
		})
	}

	function editEvent(ev) { startEditor($(this)) }

	if ($container == null)
		$(selector).on('dblclick', editEvent)
	else
		$container.on('dblclick', selector, editEvent)
}