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]]`]]            
                            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.