We are using elFinder for our software, and also using its file picker.
This is the (actually working) code:
var elfinderInstance = modalBody.elfinder({
lang: 'de',
[...],
getFileCallback: function(data) {
$("#" + fileInputId).val(data.url);
fileModal.modal("hide");
},
handlers : {
select : function(event, elfinderInstance) {
console.log(event.data.selected);
var selected = event.data.selected;
if (selected.length) {
selectedElement = elfinderInstance.url(selected[0]);
}
}
}
}).elfinder('instance');
However it is possible to select multiple files in the modal, by simply pressing the CTRL button and clicking on multiple files.
How can I disable this behaviour?
I already checked the select handler, and selected.length already returns the number of selected files but I can't figure out how to unselect the previously selected files so that only one file can be selected. I also found nothing in the Docs (https://github.com/Studio-42/elFinder/wiki).
With elFInder 2.1.17 or higher, the connector main option maxTargets is available. This is an option to suppress the load on the connector side, but it is also effective for this case.
$opts = array(
'maxTargets' => 1,
'roots' => array( .... ),
);
see https://github.com/Studio-42/elFinder/issues/2334
Related
I am developing one custom plugin for the CKEditor 4.7 which do a simple think take in case user select some stuff it will put it in a div with specific class, else it will put a div with same class just with text like 'Add content here'
I try to use some functions according to CKEditor docs but have something really wrong.
here is the code for the plugin folder name=> customdiv, file=> plugin.js
CKEDITOR.plugins.add('customdiv', {
icons: 'smile',
init: function (editor) {
editor.addCommand( 'customdiv',{
exec : function( editor ){
var selection = editor.getSelection();
if(selection.length>0){
selection='<div class="desktop">'+selection+'</div>';
}else{
selection='<div class="desktop">Add your text here </div>';
}
return {
selection
};
}
});
editor.ui.addButton( 'Customdiv',
{
label : 'Custom div',
command : 'customdiv',
toolbar: 'customdiv',
icon : this.path + 'smile.png'
});
if (editor.contextMenu) {
editor.addMenuGroup('divGroup');
editor.addMenuItem('customdiv', {
label: 'Customdiv',
icon: this.path + 'icons/smile.png',
command: 'customdiv',
group: 'divGroup'
});
editor.contextMenu.addListener(function (element) {
if (element.getAscendant('customdiv', true)) {
}
});
}
}
});
According to some docs it have to return the result good.
Also this is how I call them in my config.js file
CKEDITOR.editorConfig = function (config) {
config.extraPlugins = 'templates,customdiv';
config.allowedContent = true;
config.toolbar = 'Custom';
config.toolbar_Custom = [
{ name: 'divGroup', items: [ 'Customdiv' ] },
{name: 'document', items: ['Source', '-', 'Save', 'Preview', '-', 'Newplugin']},
/* MOre plugins options here */
];
};
Note: the official forum was close and moved here :(
UPDATE
I have change the function like this
exec : function( editor ){
var selection = editor.getSelection();
if(selection.length>0){
selection='<div class="desktop">'+selection+'</div>';
CKEDITOR.instances.editor1.insertHtml( selection );
}else{
selection='<div class="desktop">Add your text here </div>';
CKEDITOR.instances.editor1.insertHtml( selection );
}
}
This makes it work for the else part, but still can't get the selected one.
UPDATE 2
After change of the if I can get data if is selected, but when I do insert selected between <div> I face a problem.
var selection = editor.getSelection();
give like result an object, and I funded out a more complex function and I get collected data like this
var selection = editor.getSelection().getNative();
alert(selection);
from this in alert I see the proper selection and not just object,but when I insert it like
CKEDITOR.instances.editor1.insertHtml('<div class="desktop">' + selection + '</div>');
it just put all selected in one line and not adding the div, new div for else case working with this syntax.
UPDATE 3
The problem now is this function
CKEDITOR.instances.editor1.insertHtml('<div>' + selection + '<div>');
it delete all existing HTML tags even if I add just selection without <div> I am not sure if this is because of the way I insert data or way I collect data, just in alert when I collect data I see correct space like in the editor.
user select some stuff it will put it in a div with specific class
If you want to check if selection is not empty, please instead of selection.length>0 try using !selection().getRanges()[0].collapsed.
If you need something more advanced you could also try using
!!CKEDITOR.instances.editor1.getSelection().getSelectedText() to see if any text was selected and !!CKEDITOR.instances.editor1.getSelection().getSelectedElement() to see if any element like e.g. image, tabl,e widget or anchor was selected.
EDIT:
If you need selected HTML please use CKEDITOR.instances.editor1.getSelectedHtml().getHtml();
Please also have a look at CKEditor documentation:
https://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-getSelectedHtml
https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_documentFragment.html#method-getHtml
https://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection-method-getSelectedText
https://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection-method-getSelectedElement
I have looked through all of the similar questions available at the time of this question, and none of the solutions presented worked in the below code. Google was also not helpful except that I did find a few issues with dynamic code where the entire menu was not wrapped, but those issues should be fixed with either the trigger or enhanceWithin methods - which have been tried here.
I am a fairly new with javascript and the jquery library and this is my first app with jquery mobile.
The raw html as generated from the php file:
<div class="cell_container force_org_select">
<label for"force_org[new_555]" class="ui-hidden-accessible">Troop Type</label>
<select name="force_org[new_555]" id="force_org[new_555]" class="roster_cell" data-mini="true">
<option value="hq">HQ</option>
<option value="elite">Elite</option>
<option value="solo">Solitaire</option>
<option value="formation">Std Formation</option>
</select>
The Javascript function that handles the dynamic injection:
$(document).on('click','.add_item', function(event) {
event.preventDefault();
var the_link = $(this).attr('href')
var area = getParameterByName(the_link, 'area');
var type = getParameterByName(the_link, 'type');
var squad_id = getParameterByName(the_link, 'squad_id');
var vehicle = getParameterByName(the_link, 'vehicle');
var divider = getParameterByName(the_link, 'divider');
var preset = $('#preset').val();
$.post(cmd_ajax.ajaxurl,{action: 'cmd_add_item_mobile', type: type, preset: preset, squad_id: squad_id, vehicle: vehicle, divider: divider}, function(data) {
if(type == 'squad' || type == 'divider') {
$('#list').append(data).enhanceWithin();
//$('#list').append(data).trigger("refresh");
//$('#list').append(data).trigger("create");
$('.squad_help_button').tooltipster({
contentCloning: true,
trigger: 'custom',
triggerOpen: {
click: true,
tap: true
},
triggerClose: {
click: true,
tap: true
}
});
}
else {
$('#' + area).append(data).enhanceWithin();
}
//console.log("squad_id:"+this_id);
set_unit_sortable();
});
return false;
});
I also tried adding the .selectmenu("refresh",true) within the function and that seems to do nothing. The custom selects that are not dynamically generated work fine.
If I use the data-native-menu="false" attribute on the generated select menus, the popup does not function and you cannot select anything, if I remove the attribute, the native select works as it should.
I thought about using a selectmenu() refresh at the very end of the function, but I can't seem to catch the element id of the select menu either. My only guess is that it isn't created yet in the DOM when I try to retrieve it.
I have more than 5 tabs in a metabox. In every metabox i have a bootstrap modal for image variations holding some inputs and a button with class of .btn.select_media_ and a data-id attribute which holding unique ID of that tab. I am opening wp uploader on click of this button. please see my JS code.
var mediaUploader;
$(document).on('click','.btn.select_media_',function(e){
e.preventDefault();
var id=$(this).data('id');
// If the uploader object has already been created, reopen the dialog
console.log('clicked:'+id);
if (mediaUploader) {
mediaUploader.open();
return;
}
// Extend the wp.media object
mediaUploader = wp.media.frames.file_frame = wp.media({
///mediaUploader = wp.media.frames.mediaUploader = wp.media({
title: 'Choose Image',
button: {
text: 'Choose Image'
}, multiple: false });
mediaUploader.on('select', function() {
attachment = mediaUploader.state().get('selection').first().toJSON();
$('#img_url_'+ id).val(attachment.url);
$('#img_width_'+ id).val(attachment.width+'px');
$('#img_title_'+ id).val(attachment.title);
$('#show_img_'+ id).attr('src',attachment.url);
console.log('selected'+ id);
});
// Open the uploader dialog
mediaUploader.open();
});
Problem is that when i set/upload an image in any one tab this function run and set value of images in mideaUploader.on('select') event. when i am try to select image in an other tab i noticed in console that console.log('selected'+ id); had old value (on which tab i set first time) and console.log('clicked'+ id); had newer id value.
Please help!, what is wrong with my code? and how can i get same value at top and bottom of this handler?
Its good i solved my problem by declaring a global object and assign data-id value to this object.
I am building a pretty combobox with checkboxes and conditional entries. Everything works out alright, except for two features that I cannot figure out how to implement.
1) I would like to move the label inside the combobox, make it shift the values to the right, and appear in a slightly gray color.
2) I would like the value to ignore certain entries (group headers) selected. Those entries are there for functionality only - to select/unselect groups of other entries.
The entire project is in the zip file. You don't need a server, it's a client base app. Just download the archive, unpack, and launch app.html in your browser.
http://filesave.me/file/30586/project-zip.html
And here's a snapshot of what I would like to achieve.
Regarding your second issue, the best way I see is to override combobox onListSelectionChange to filter the values you don't want:
onListSelectionChange: function(list, selectedRecords) {
//Add the following line
selectedRecords = Ext.Array.filter(selectedRecords, function(rec){
return rec.data.parent!=0;
});
//Original code unchanged from here
var me = this,
isMulti = me.multiSelect,
hasRecords = selectedRecords.length > 0;
// Only react to selection if it is not called from setValue, and if our list is
// expanded (ignores changes to the selection model triggered elsewhere)
if (!me.ignoreSelection && me.isExpanded) {
if (!isMulti) {
Ext.defer(me.collapse, 1, me);
}
/*
* Only set the value here if we're in multi selection mode or we have
* a selection. Otherwise setValue will be called with an empty value
* which will cause the change event to fire twice.
*/
if (isMulti || hasRecords) {
me.setValue(selectedRecords, false);
}
if (hasRecords) {
me.fireEvent('select', me, selectedRecords);
}
me.inputEl.focus();
}
},
And change your onBoundlistItemClick to only select and deselect items in the boundlist not to setValue of the combo:
onBoundlistItemClick: function(dataview, record, item, index, e, eOpts) {
var chk = item.className.toString().indexOf('x-boundlist-selected') == -1;
if ( ! record.data.parent) {
var d = dataview.dataSource.data.items;
for (var i in d) {
var s = d[i].data;
if (s.parent == record.data.id) {
if (chk) { // select
dataview.getSelectionModel().select(d[i],true);
} else { // deselect
dataview.getSelectionModel().deselect(d[i]);
}
}
}
}
},
Regarding your first issue, it is easy to add the label using the displayTpl config option. But this will only add the text you need, without any style (grey color, etc). The combo is using a text input, which does not accept html tags. If you don't need the user to type text, than you may want to change the combo basic behavior and use another element instead of the text input.
I'm adding a custom context menu item to documents (and not folders) in a SPDocumentLibrary list in SharePoint. The following code works, but always adds my custom menu item at the top of the context menu, which I don't want. I was guessing that the final parameter in CAMOpt was a sequence number that would define the order, but it doesn't seem to have any effect. Does anyone know if it's possible to add a custom context menu item to the bottom on the list?
function Custom_AddDocLibMenuItems(m, ctx) {
var otype = currentItemFSObjType = GetAttributeFromItemTable(itemTable, "OType", "FSObjType");
if (otype != 1) {
var itemId = GetAttributeFromItemTable(itemTable, "ItemId", "Id");
var listId = ctx.listName;
var action = 'Go_To_Page("' + ctx.HttpRoot + '/_layouts/custom/PAGES/mycustompage.aspx?ListId=' + listId + '&ListItemID=' + itemId + ');';
CAMOpt(m, 'Custom Menu Item', action, '/_layouts/custom/IMAGES/action.gif', '', 110);
CAMSep(m);
}
return false;
}
function Go_To_Page(page) {
window.location = page;
}
Is there any reason why you aren't able to use a custom action feature? For example use feature element code similar to the following but amend the Sequence number of the CustomAction element to locate the menu option:
<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Id="DoSomething"
RegistrationType="ContentType"
RegistrationId="0x0101"
Location="EditControlBlock"
Sequence="10001"
ImageUrl="/_layouts/images/action.gif"
Title="Do Something">
<UrlAction Url="~site/_layouts/custom/PAGES/mycustompage.aspx?ListItemID={ItemId}&ListId={ListId}" />
</CustomAction>
</Elements>
Setting the content type should ensure the feature doesn't apply to folders. If for some reason it is showing and there appears to be no way to disable it, you could use JavaScript/jQuery to hide the menu option from folders.
In the elements XML for your feature where you include the User Control, add the sequence there:
Control Id="AdditionalPageHead"
ControlSrc="~/_ControlTemplates/blah/blah.ascx" Sequence="229"