我想在summernote对话框中使用一个转发器字段。我正在使用jquery.repeater library。
在我的最小可行示例下面查找:
$(document).ready(function() {
$('.summernote').summernote({
height: 300,
tabsize: 2,
toolbar: [
['insert', ['synonym', 'codeview']]
],
});
});
(function(factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(window.jQuery);
}
}(function($) {
$.extend($.summernote.plugins, {
'synonym': function(context) {
var self = this;
var ui = $.summernote.ui;
var $editor = context.layoutInfo.editor;
var options = context.options;
context.memo('button.synonym', function() {
return ui.button({
contents: '<i class="fa fa-snowflake-o">',
tooltip: 'Create Synonym',
click: context.createInvokeHandler('synonym.showDialog')
}).render();
});
self.initialize = function() {
var $container = options.dialogsInBody ? $(document.body) : $editor;
var body = '<div class="form-group">' +
'IF(<input type="text" name="text-input" value="A"/>) <input type="text" name="text-input" value="A"/>' +
'<div data-repeater-list="group-a">' +
'<div data-repeater-item>' +
'<select name="select-input">' +
'<option value="A" selected>ELSE</option>' +
'<option value="B">ELSEIF</option>' +
'</select>' +
'(<input type="text" name="text-input" value="A"/>)' +
'<input type="text" name="text-input" value="A"/>' +
'<input data-repeater-delete type="button" value="Delete"/>' +
'</div>' +
'</div>' +
'<input data-repeater-create type="button" value="Add"/>' +
'<br/>' +
'@ENDIF'
var footer = '<button href="#" class="btn btn-primary ext-ifElse-btn">OK</button>';
self.$dialog = ui.dialog({
title: 'minimal dialog title',
fade: options.dialogsFade,
body: body,
footer: footer
}).render().appendTo($container);
};
self.destroy = function() {
self.$dialog.remove();
self.$dialog = null;
};
self.showDialog = function() {
self
.openDialog()
.then(function(data) {
// [workaround] hide dialog before restore range for IE range focus
ui.hideDialog(self.$dialog);
context.invoke('editor.restoreRange');
self.insertToEditor(data);
// do something with dialogData
console.log("dialog returned: ", data)
// ...
})
.fail(function() {
context.invoke('editor.restoreRange');
});
};
self.openDialog = function() {
return $.Deferred(function(deferred) {
var $dialogBtn = self.$dialog.find('.ext-synonym-btn');
var $elemInput = self.$dialog.find('#input-element')[0];
var $synonymInput = self.$dialog.find('#input-synonym')[0];
var selectedText = $.selection()
$('#input-element').val(selectedText);
console.log("show dialog: " + selectedText)
ui.onDialogShown(self.$dialog, function() {
context.triggerEvent('dialog.shown');
$dialogBtn
.click(function(event) {
event.preventDefault();
deferred.resolve({
element: $elemInput.value,
synonym: $synonymInput.value
});
});
});
ui.onDialogHidden(self.$dialog, function() {
$dialogBtn.off('click');
if (deferred.state() === 'pending') {
deferred.reject();
}
});
ui.showDialog(self.$dialog);
});
};
this.insertToEditor = function(data) {
console.log("synonym: " + data.synonym)
var $elem = $('<synonym>', {
words: data.synonym
});;
$elem.text(data.element)
context.invoke('editor.insertNode', $elem[0]);
};
}
});
}));
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.10/summernote.css" />
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.10/summernote.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.selection/1.0.1/jquery.selection.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.repeater/1.2.1/jquery.repeater.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// repeater field
$(document).ready(function() {
$('.repeater').repeater({
defaultValues: {
'textarea-input': 'foo',
'text-input': 'bar',
'select-input': 'B'
},
show: function() {
$(this).slideDown();
},
hide: function(deleteElement) {
/*
if(confirm('Are you sure you want to delete this element?')) {
$(this).slideUp(deleteElement);
}
*/
},
ready: function(setIndexes) {
}
});
window.outerRepeater = $('.outer-repeater').repeater({
isFirstItemUndeletable: true,
defaultValues: {
'text-input': 'outer-default'
},
show: function() {
console.log('outer show');
$(this).slideDown();
},
hide: function(deleteElement) {
console.log('outer delete');
$(this).slideUp(deleteElement);
},
repeaters: [{
isFirstItemUndeletable: true,
selector: '.inner-repeater',
defaultValues: {
'inner-text-input': 'inner-default'
},
show: function() {
console.log('inner show');
$(this).slideDown();
},
hide: function(deleteElement) {
console.log('inner delete');
$(this).slideUp(deleteElement);
}
}]
});
});
});
</script>
<div class="container">
<div class="summernote">
<p>Hello World!</p>
This text should be replaced by the dialog. </div>
</div>
<!-- START -->
IF(<input type="text" name="text-input" value="A"/>) <input type="text" name="text-input" value="A"/>
<div data-repeater-list="group-a">
<div data-repeater-item>
<select name="select-input">
<option value="A" selected>ELSE</option>
<option value="B">ELSEIF</option>
</select>
(<input type="text" name="text-input" value="A"/>)
<input type="text" name="text-input" value="A"/>
<input data-repeater-delete type="button" value="Delete"/>
</div>
</div>
<input data-repeater-create type="button" value="Add"/>
<br>
@ENDIF
<!-- START -->
如按snowflake
按钮时所看到的,转发器字段不起作用。因此,当按下Add
时,对话框中不会再添加其他字段。
有人建议我在做什么错吗?
感谢您的答复!
答案 0 :(得分:1)
您必须在要重复的包装器中分配repeater
。测试下面的代码,滚动到底部。
$(document).ready(function() {
$('.summernote').summernote({
height: 300,
tabsize: 2,
toolbar: [
['insert', ['synonym', 'codeview']]
],
});
});
(function(factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(window.jQuery);
}
}(function($) {
$.extend($.summernote.plugins, {
'synonym': function(context) {
var self = this;
var ui = $.summernote.ui;
var $editor = context.layoutInfo.editor;
var options = context.options;
context.memo('button.synonym', function() {
return ui.button({
contents: '<i class="fa fa-snowflake-o">',
tooltip: 'Create Synonym',
click: context.createInvokeHandler('synonym.showDialog')
}).render();
});
self.initialize = function() {
var $container = options.dialogsInBody ? $(document.body) : $editor;
var body = '<div class="form-group">' +
'IF(<input type="text" name="text-input" value="A"/>) <input type="text" name="text-input" value="A"/>' +
'<div data-repeater-list="group-a">' +
'<div data-repeater-item>' +
'<select name="select-input">' +
'<option value="A" selected>ELSE</option>' +
'<option value="B">ELSEIF</option>' +
'</select>' +
'(<input type="text" name="text-input" value="A"/>)' +
'<input type="text" name="text-input" value="A"/>' +
'<input data-repeater-delete type="button" value="Delete"/>' +
'</div>' +
'</div>' +
'<input data-repeater-create type="button" value="Add"/>' +
'<br/>' +
'@ENDIF'
var footer = '<button href="#" class="btn btn-primary ext-ifElse-btn">OK</button>';
self.$dialog = ui.dialog({
title: 'minimal dialog title',
fade: options.dialogsFade,
body: body,
footer: footer
}).render().appendTo($container);
};
self.destroy = function() {
self.$dialog.remove();
self.$dialog = null;
};
self.showDialog = function() {
self
.openDialog()
.then(function(data) {
// [workaround] hide dialog before restore range for IE range focus
ui.hideDialog(self.$dialog);
context.invoke('editor.restoreRange');
self.insertToEditor(data);
// do something with dialogData
console.log("dialog returned: ", data)
// ...
})
.fail(function() {
context.invoke('editor.restoreRange');
});
};
self.openDialog = function() {
return $.Deferred(function(deferred) {
var $dialogBtn = self.$dialog.find('.ext-synonym-btn');
var $elemInput = self.$dialog.find('#input-element')[0];
var $synonymInput = self.$dialog.find('#input-synonym')[0];
var selectedText = $.selection()
$('#input-element').val(selectedText);
console.log("show dialog: " + selectedText)
ui.onDialogShown(self.$dialog, function() {
context.triggerEvent('dialog.shown');
$dialogBtn
.click(function(event) {
event.preventDefault();
deferred.resolve({
element: $elemInput.value,
synonym: $synonymInput.value
});
});
});
ui.onDialogHidden(self.$dialog, function() {
$dialogBtn.off('click');
if (deferred.state() === 'pending') {
deferred.reject();
}
});
ui.showDialog(self.$dialog);
});
};
this.insertToEditor = function(data) {
console.log("synonym: " + data.synonym)
var $elem = $('<synonym>', {
words: data.synonym
});;
$elem.text(data.element)
context.invoke('editor.insertNode', $elem[0]);
};
}
});
}));
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.10/summernote.css" />
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.10/summernote.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.selection/1.0.1/jquery.selection.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.repeater/1.2.1/jquery.repeater.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// repeater field
$(document).ready(function() {
$('.repeater').repeater({
defaultValues: {
'textarea-input': 'foo',
'text-input': 'bar',
'select-input': 'B'
},
show: function() {
$(this).slideDown();
},
hide: function(deleteElement) {
/*
if(confirm('Are you sure you want to delete this element?')) {
$(this).slideUp(deleteElement);
}
*/
},
ready: function(setIndexes) {
}
});
window.outerRepeater = $('.outer-repeater').repeater({
isFirstItemUndeletable: true,
defaultValues: {
'text-input': 'outer-default'
},
show: function() {
console.log('outer show');
$(this).slideDown();
},
hide: function(deleteElement) {
console.log('outer delete');
$(this).slideUp(deleteElement);
},
repeaters: [{
isFirstItemUndeletable: true,
selector: '.inner-repeater',
defaultValues: {
'inner-text-input': 'inner-default'
},
show: function() {
console.log('inner show');
$(this).slideDown();
},
hide: function(deleteElement) {
console.log('inner delete');
$(this).slideUp(deleteElement);
}
}]
});
});
});
</script>
<div class="container">
<div class="summernote">
<p>Hello World!</p>
This text should be replaced by the dialog. </div>
</div>
<div class="repeater">
<!-- START -->
IF(<input type="text" name="text-input" value="A" />) <input type="text" name="text-input" value="A" />
<div data-repeater-list="group-a">
<div data-repeater-item>
<select name="select-input">
<option value="A" selected>ELSE</option>
<option value="B">ELSEIF</option>
</select>
(<input type="text" name="text-input" value="A" />)
<input type="text" name="text-input" value="A" />
<input data-repeater-delete type="button" value="Delete" />
</div>
</div>
<input data-repeater-create type="button" value="Add" />
<br> @ENDIF
</div>
<!-- START -->