TicketForm - количество загружаемых файлов
У меня несколько разделов на тикетах.
В разных формах нужно определить разное количество загружаемых изображений к тикетам, в одних 5 штук, в других 3 например.
И таких разделов немало, то есть нужно решение универсальное и настраиваемое для каждой из форм, а не ограничивать для всех форм на сайте.
Как реализовать такой вот лимит для прикрепляемых пользователем изображений через TicketForm?
Куда копать?
В разных формах нужно определить разное количество загружаемых изображений к тикетам, в одних 5 штук, в других 3 например.
И таких разделов немало, то есть нужно решение универсальное и настраиваемое для каждой из форм, а не ограничивать для всех форм на сайте.
Как реализовать такой вот лимит для прикрепляемых пользователем изображений через TicketForm?
Куда копать?
Поблагодарить автора
Отправить деньги
Комментарии: 31
Неужели нельзя сделать такое ограничение на количество файлов?
Как вариант через плагин на onBeforeDocFormSave.
Да нет, тут похоже нужно Javascript задействовать для контроля, ведь загрузчик-то Plupload…
Вот пытаюсь вклинится в его работу, но не хочется трогать файл компонента
Вот пытаюсь вклинится в его работу, но не хочется трогать файл компонента
assets/components/tickets/js/web/files.js
Вот и сижу, ломаю себе голову… ))
Тогда могу предложить такой вариант — создай свой js и подключай его в шаблоне для тикета. А в js просто повесь событие на загрузку. Типа такого
П.С. Это для стандартных шаблонов Tickets.
$(document).on('click', '#ticket-files-select', function(e) {
if ($('div.ticket-file-image-wrapper').length == 3) {
alert('Больше трех картинок низя!');
return false;
}
});
Не тестировал, но идея должна быть понятна.П.С. Это для стандартных шаблонов Tickets.
Работает, но тут проблема в мультизагрузке. Мультизагрузкой загрузить можно хоть 100 фоток и отправить…
www.plupload.com/docs/Options — грызу гранит доков… Думаю как вклиниться в вызов.
www.plupload.com/docs/Options — грызу гранит доков… Думаю как вклиниться в вызов.
Отключи мультизагрузку через multi_selection в files.js.
multi_selection: false,
У меня получилогсь сделать. Допиливал files.js. Могу кинуть подробно все шаги, мультизагрузка тоже учтена и она работает. ) Но, чувствую, не самый оптимальный способ(т.к. опыт небольшой), но рабочий.
О! Давай!!!
Я вот тоже мучаю этот файл, впихиваю в FilesAdded проверки.
А ещё пытаюсь инициализировать отдельно в моих скриптах и перезаписать вызов из files.js, но тоже не получается, ругается что
Мучаю этот кусок кода:
Я вот тоже мучаю этот файл, впихиваю в FilesAdded проверки.
А ещё пытаюсь инициализировать отдельно в моих скриптах и перезаписать вызов из files.js, но тоже не получается, ругается что
Uncaught ReferenceError: Tickets is not defined
Мучаю этот кусок кода:
var max = 3; // max number of files
Tickets.Uploader.bind('FilesAdded', function(up, files) {
if (files.length > max)
alert('You are allowed to add only ' + max + ' files.');
uploader.splice(); // reset the queue to zero
}
Создал дополнительное поле [[*max-photo]]. Прикрепил к ресурсу, на котором будет вызов формы. Форму создал отдельную, на вскйи случай photo.tpl.Tickets.form.create:
Далее…
<form class="well create" method="post" action="" id="ticketForm">
<div id="ticket-preview-placeholder"></div>
<input type="hidden" name="tid" value="0" />
<div class="form-group">
<label for="ticket-sections">Выберете альбом</label>
<select name="parent" class="form-control" id="ticket-sections">[[+sections]]</select>
<span class="error"></span>
</div>
<div class="form-group">
<label for="ticket-pagetitle">[[%ticket_pagetitle]]</label>
<input type="text" class="form-control" placeholder="[[%ticket_pagetitle]]" name="pagetitle" value="" maxlength="50" id="ticket-pagetitle"/>
<span class="error"></span>
</div>
<div class="form-group">
<textarea class="form-control" placeholder="[[%ticket_content]]" name="content" id="ticket-editor" rows="10"></textarea>
<span class="error"></span>
</div>
<div class="ticket-form-files">
[[+files]]
</div>
<div class="form-actions row">
<div class="col-md-6">
<input type="button" class="btn btn-default preview" value="[[%ticket_preview]]" title="Ctrl + Enter" />
</div>
<div class="col-md-6 move-right">
<!--<input type="button" class="btn btn-primary publish" name="publish" value="[[%ticket_publish]]" title="" /> -->
<div id="ajax_hide_limit"><input type="submit" class="btn btn-danger draft" name="draft" value="Отправить на модерацию" title="Ctrl + Shift + Enter" /></div>
</div>
</div>
</form>
<strong>Количество загруженных фотографий:</strong><div style="display:inline-block;" id="ajax_test_value">[[!temp-count-photo? &id=`[[*id]]` &userId=`[[!+modx.user.id]]`]]</div> из <div style="display:inline-block;" id="ajax_max_value">[[*max-photo]]</div>
<div id="ajax_test_block" ></div>
Далее…
Вот мой код files.js:
Блеать! тикеткс обновил что-ли… ща, пороюсь
Вот-вот и я о том же… Тикетс обновится и всё полетит. Нужно или
1. делать копии файлов в случае обновления и следить за их заменой после каждого обновления,
2. или как-то поймать и переинициализировать Plupload с подсчётом максимального количества.
Плюс второго варианта в том, что для разных форм можно будет указывать разное количество максимальных файлов.
Как найдёшь код своего files.js скинь его тоже!
1. делать копии файлов в случае обновления и следить за их заменой после каждого обновления,
2. или как-то поймать и переинициализировать Plupload с подсчётом максимального количества.
Плюс второго варианта в том, что для разных форм можно будет указывать разное количество максимальных файлов.
Как найдёшь код своего files.js скинь его тоже!
Ок, я ща порпобую сделать откат до субботы, скопирую, и возвращусь)
Надеюсь, он не пропал)))
Ну мой как раз тоже и предусматриает это через [[*max-photo]] .)
Надеюсь, он не пропал)))
Ну мой как раз тоже и предусматриает это через [[*max-photo]] .)
А, да. У тебя там ещё есть сниппет [[!temp-count-photo]]
Да, там просто такая ситуация. Если авторизваонный чувак, закидывает фоты и уходит со страницы, не отправляя… но потом возвращается на страницу с формой. Все загруженные фоты ранее остаются… и если не учитваеть это(алерт тут уже не поможет), то вся история напрасна. Я скрываю кнопку в таком случае «отправить». В ближайшее время постараюсь восстановить.
Интересно, понятно. Спасибо!
var form = $('#comment-form');
if (!form.length) {
form = $('#ticketForm');
}
Tickets.Uploader = new plupload.Uploader({
runtimes: 'html5,flash,silverlight,html4',
browse_button: 'ticket-files-select',
//upload_button: document.getElementById('ticket-files-upload'),
container: 'ticket-files-container',
filelist: 'ticket-files-list',
progress: 'ticket-files-progress',
progress_bar: 'ticket-files-progress-bar',
progress_count: 'ticket-files-progress-count',
progress_percent: 'ticket-files-progress-percent',
form: form,
multipart_params: {
action: $('#' + this.container).data('action') || 'ticket/file/upload',
tid: this.form.find('[name="tid"]').val(),
form_key: this.form.find('[name="form_key"]').val(),
ctx: TicketsConfig.ctx || 'web'
},
drop_element: 'ticket-files-list',
url: TicketsConfig.actionUrl,
filters: {
max_file_size: TicketsConfig.source.size,
mime_types: [{
title: 'Files',
extensions: TicketsConfig.source.extensions
}]
},
resize: {
width: TicketsConfig.source.width,
height: TicketsConfig.source.height
},
flash_swf_url: TicketsConfig.jsUrl + 'web/lib/plupload/js/Moxie.swf',
silverlight_xap_url: TicketsConfig.jsUrl + 'web/lib/plupload/js/Moxie.xap',
init: {
Init: function(up) {
if (this.runtime == 'html5') {
var element = $(this.settings.drop_element);
element.addClass('droppable');
element.on('dragover', function() {
if (!element.hasClass('dragover')) {
element.addClass('dragover');
}
});
element.on('dragleave drop', function() {
element.removeClass('dragover');
});
}
},
PostInit: function(up) {},
FilesAdded: function(up, files) {
this.settings.form.find('[type="submit"]').attr('disabled',true);
up.start();
},
UploadProgress: function(up, file) {
$(up.settings.browse_button).hide();
$('#' + up.settings.progress).show();
$('#' + up.settings.progress_count).text((up.total.uploaded + 1) + ' / ' + up.files.length);
$('#' + up.settings.progress_percent).text(up.total.percent + '%');
$('#' + up.settings.progress_bar).css('width', up.total.percent + '%');
},
FileUploaded: function(up, file, response) {
response = $.parseJSON(response.response);
if (response.success) {
// Successfull action
/*Моя фича*/
var maxPhoto=$("#ajax_max_value").html()
maxPhoto = parseInt(maxPhoto);
var count=$("#ajax_test_value").html()
count = parseInt(count);
var type="test";
$.ajax({
data: {type:type},
type: "POST",
url: "/аякс-загрузка-фоток.html",
success: function ( data ) {
count++;
$("#ajax_test_value").html(count);
if(count>=maxPhoto){
$("#ticket-files-container").hide();
$("#max-response").show();
}
if(count>maxPhoto){
$("#ajax_hide_limit").hide();
}
else{
$("#ajax_hide_limit").show();
}
/* $("#ajax_test_block").html(count);*/
/*$("#ticket-files-select").hide();*/
}
});
/*конец моей фичи*/
var files = $('#' + up.settings.filelist);
var clearfix = files.find('.clearfix');
if (clearfix.length != 0) {
$(response.data).insertBefore(clearfix);
}
else {
files.append(response.data);
}
}
else {
Tickets.Message.error(response.message);
}
},
UploadComplete: function(up, file, response) {
$(up.settings.browse_button).show();
$('#' + up.settings.progress).hide();
up.total.reset();
up.splice();
this.settings.form.find('[type="submit"]').attr('disabled',false);
},
Error: function(up, err) {
Tickets.Message.error(err.message);
}
}
});
Tickets.Uploader.init();
$(document).on('click', '.ticket-file-delete', function(e) {
var deleted = 'deleted';
var $this = $(this);
var $form = $this.parents('form');
var $parent = $this.parents('.ticket-file');
var id = $parent.data('id');
var form_key = $form.find('[name="form_key"]').val();
$.post(TicketsConfig.actionUrl, {action: 'ticket/file/delete', id: id, form_key: form_key}, function(response) {
/*Моя фича*/
var maxPhoto=$("#ajax_max_value").html()
maxPhoto = parseInt(maxPhoto);
var count=$("#ajax_test_value").html()
count = parseInt(count);
var type="test";
$.ajax({
data: {type:type},
type: "POST",
url: "/аякс-загрузка-фоток.html",
success: function ( data ) {
count--;
$("#ajax_test_value").html(count);
if(count>=maxPhoto){
$("#ticket-files-container").hide();
$("#max-response").show();
}
else {$("#ticket-files-container").show();
$("#max-response").hide();
}
if(count>maxPhoto){
$("#ajax_hide_limit").hide();
}
else{
$("#ajax_hide_limit").show();
}
/* $("#ajax_test_block").html(count);*/
/*$("#ticket-files-select").hide();*/
}
});
/*конец моей фичи*/
if (response.success) {
if ($parent.hasClass(deleted)) {
$parent.removeClass(deleted)
}
else {
$parent.addClass(deleted)
}
}
else {
Tickets.Message.error(response.message);
}
}, 'json');
return false;
});
$(document).on('click', '.ticket-file-restore', function(e) {
var deleted = 'deleted';
var $this = $(this);
var $form = $this.parents('form');
var $parent = $this.parents('.ticket-file');
var id = $parent.data('id');
var form_key = $form.find('[name="form_key"]').val();
$.post(TicketsConfig.actionUrl, {action: 'ticket/file/delete', id: id, form_key: form_key}, function(response) {
/*Моя фича*/
var maxPhoto=$("#ajax_max_value").html()
maxPhoto = parseInt(maxPhoto);
var count=$("#ajax_test_value").html()
count = parseInt(count);
var type="test";
$.ajax({
data: {type:type},
type: "POST",
url: "/аякс-загрузка-фоток.html",
success: function ( data ) {
count++;
$("#ajax_test_value").html(count);
if(count>=maxPhoto){
$("#ticket-files-container").hide();
$("#max-response").show();
}
else {$("#ticket-files-container").show();
$("#max-response").hide();
}
if(count>maxPhoto){
$("#ajax_hide_limit").hide();
}
else{
$("#ajax_hide_limit").show();
}
/* $("#ajax_test_block").html(count);*/
/*$("#ticket-files-select").hide();*/
}
});
/*конец моей фичи*/
if (response.success) {
if ($parent.hasClass(deleted)) {
$parent.removeClass(deleted)
}
else {
$parent.addClass(deleted)
}
}
else {
Tickets.Message.error(response.message);
}
}, 'json');
return false;
});
$(document).on('click', '.ticket-file-insert', function(e) {
var $this = $(this);
var $parent = $this.parents('.ticket-file');
var $text = $('[name="content"]');
var template = $parent.find('.ticket-file-template').html();
template = template.replace(/^\n/g, '').replace(/\t{2}/g, '').replace(/\t$/g, '');
$text.focus();
$.markItUp({replaceWith: template});
return false;
});
Это files.js Ща другое распишу…Тут учтены в том числе варианты с восстановлением фоток и их удалением в форме.
$(document).ready(function() {
var maxPhoto=$("#ajax_max_value").html()
maxPhoto = parseInt(maxPhoto);
var count=$("#ajax_test_value").html()
count = parseInt(count);
if(count>maxPhoto){
$("#ajax_hide_limit").hide();
}
if(count<=maxPhoto){
$("#ajax_hide_limit").show();
}
})
Это подключаемый скрипт к странице с формой.
Это
temp-count-photo:
<?php
$userId;
$modx->getObject('TicketFile');
return $count = $modx->getCount('TicketFile', array('parent'=>0, 'createdby'=>$userId));
Сейчас, еще кое-что никак не вспомню…
Во! Это tpl.Tickets.form.files:
<div id="ticket-files-list">
[[+files]]
<div class="clearfix"></div>
</div>
<div id="ticket-files-container" data-action="ticket/file/upload">
<a id="ticket-files-select" href="javascript:;">[[%ticket_file_select]]</a>
<div id="ticket-files-progress">
<span id="ticket-files-progress-count">0/0</span>
<span id="ticket-files-progress-percent">0%</span>
<div id="ticket-files-progress-bar"></div>
</div>
</div>
<span style="display:none;" id="max-response"><strong>Лимит исчерпан</strong></span>
Вроде все) Учти все id в формах при подключении.
Спасибо! Сейчас буду разбираться и прикручивать по-тихоньку…
Пожалуйста. Теперь хоть сам отсюда смогу восстановить, если вдруг чего опять)))
Получается следующая система. Можно закидывать и мультиаплодно, тогда при превышении укзаанного лимита, скрывается кнопка «отправить». Учитывается ссылки к каждой добавленной фоте «восстановить» и «удалить». И при уходе со страницы и возвращении на нее, количество загруженных фоток ранее учитывается и форма показывает превышение лимита, убирая кнопку «отправить».
Вот это я уже не помню правда
$.ajax({
data: {type:type},
type: "POST",
url: "/аякс-загрузка-фоток.html",
в files.js для чего посылал, скорее всего там у меня был првоерчный сниппет, который показывал, прокатывал POST или нет у меня на странице. Соотв-но можно без него обойтись.
а я влез в тикетовый процессор web/upload/file, и в методе process() дописал после проверки на дубли:
Хочется попросить Василия что-то подобное таки включить в релиз, полезная штука.
// Check for files limit
if ($filesLimit = $this->modx->getOption('tickets.max_files_upload')) {
$checkLimit = $this->modx->newQuery($this->classKey, array('class' => $this->class));
if (!empty($this->ticket->id)) {
$checkLimit->andCondition(array('parent:IN' => array(0, $this->ticket->id)));
} else {
$checkLimit->andCondition(array('parent' => 0));
}
$checkLimit->andCondition(array('createdby' => $this->modx->user->id));
if ($this->modx->getCount($this->classKey, $checkLimit) >= $filesLimit) {
@unlink($data['tmp_name']);
return $this->failure('Вы не можете загрузить больше '.$filesLimit.' файлов');
}
}
и джаваскрипт можно не трогать, и надежнее.Хочется попросить Василия что-то подобное таки включить в релиз, полезная штука.
Может добавиш pull-request на гитхаб?
Посмотрим на реакцию Василия…
Посмотрим на реакцию Василия…
Да чётко работает. Спасибо!
А ни кто не знает как вывести на фронтенде количество загруженных файлов к тикету?
Для доски объявлений нужно…
Для доски объявлений нужно…
оказалось всё просто)
<?php
$parentId;
$modx->getObject('TicketFile');
return $count = $modx->getCount('TicketFile', array('parent'=>$parentId));
И вывести сниппет так: [[название-сниппета? &parentId=`[[+id]]`]]
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.