Пользователь
0,0
рейтинг
16 ноября 2009 в 20:15

Разработка → jQuery плагин для получения данных формы + ajax аплоадер файлов

imageДоброго времени суток, уважаемое Хабросообщество! Не пытаясь скрыть легкое волнение, публикую свой первый пост, темой которого стал мой скромный jQuery-велосипед для быстрого и безболезненного сбора данных, введенных пользователем на странице (сразу небольшая оговорка для тех, кто закричит — «ату его! Зачем еще один подобный плагин?», отвечу: во-первых — а быть может именно это кто-то из хаброчитателей и искал, во-вторых — для саморазвития, в-третьх: для собственного удобства и безболезненного использования в своих програмных продуктах).

Итак, помимо, собственно моего небольшого плагина, нам понадобится сам jQuery последней версии, а так же небольшой плагин к нему, реализующий преобразование объектов\массивов в json-строку, для того, чтобы полученные данные можно было быстренько передавать на сервер.
updated

updated 2 — добавлена мультизагрузка!



А теперь приступим к описанию методов плагина. Их немного :) Точнее — три.

Первый: $.form.get(formName,toJson,multi). Функция возвращает данные с указанной формы в виде массива или json-строки. Коротко о главном, то есть о входных переменных.
  • formName — как следует из названия, передаем сюда имя формы.
  • toJsontrue/false. Если true — то возвращается json-строка, содержащая значения формы. Если же false — то объект. По умолчанию — true.
  • multi — так же принимает true/false. Если передано true, то функция понимает, что инпутов с одинаковым именем на странице может быть несколько, и собирает значения всех этих одноименных элементов формы в понумерованный массив. Передавая false, мы указываем, что одноименных input'ов на форме не предвидится, и можно не колеблясь запихивать значения в виде строки (исключения составляют элементы select с аттрибутом multiple и чекбоксы). По-умолчанию передается false;

Второй: $.form.set(formName,elemName,value) Служит для установки новых значений для элемента формы. Входные параметры:
  • formName — то же, что и в предыдущей функции.
  • elemName — значение аттрибута name элемента формы
  • value — строка или массив, содержащий новые значения элемента.

Третий: $.form.save(params) По сути дела, это обертка, получающая необходимую форму и отправляющая ее посредством post запроса на сервер. Входной параметр один, это объект следующего вида:
{
    name: "", //имя формы
    url: "", //адрес серверного скрипта
    params: {}, //объект, содержащий дополнительные параметры, передаваемые серверному скрипту
    multi: false, //то же, что и в предыдущих функциях
    test: false, //true/false — если true, то ответ сервера выводится с помощью функции alert
    callback: function(data){}, //функция, вызываемая после выполнения post-запроса. Принимает в качестве единственного параметра ответ сервера.
}
Если какой-то из параметров не передан, то они заменятся на значения по-умолчанию. Но понятно, что если не передать name и url, то получится билеберда =)

Ну и последнее: для того, чтобы указать имя формы для элементов input, select и textarea я использовал аттрибут class. Изначально попробовал ввести свой аттрибут form, но это оказалось не кроссбраузерно)


Код плагина в конце статьи

UPD

Итак, обновил скрипт и демо. Теперь плагин поддерживает ajax-upload файлов с прогрессбаром. Flash для загрузчика не требуется. Для отображения прогрессбара используется jQueryUI.

Для того, чтобы использовать input:file с нашим плагином, добавляем на страницу элемент, подобный этому:
<input type=«file» name=«file» class=«upload»>
Далее, на событие document.ready вешаем функцию, преобразующую этот инпут в наш ajax-загрузчик:

$.form.makeUpload('.upload[name=test]',{
    upload:'upload.php?action=uploadFile',
    progress:'upload.php?action=progress',
    directory:'uploads',
    multi:true,
    autoUpload:true
});

Вот что получается в итоге:
image

Получать данные с таким элементов можно все той же функцией $.form.get

Возвращаемые после загрузки файла значения:
  • directory — директория на сервере, куда был загружен файл
  • serverFileName — имя файла на сервере
  • path — directory+"/"+serverFileName
  • size — размер файла в байтах
  • isUploaded — 0 или 1. А был ли вообще загружен файл? :)

Функция $.form.makeUpload принимает два входящих параметра
  • multi — разрешить мультизагрузку, true\false. False по-умолчанию
  • selector — селектор объекта\объектов, которые нужно преобразовать в загрузчик
  • params — объект со следующими ключами:
    • upload — адрес серверного скрипта, который отвечает за upload файла
    • progress — адрес серверного скрипта, который отображает прогресс загрузки файла
    • serverFileName — имя, которое будет присвоено файлу на сервере. Если в этом параметре встречается слово %real%, то оно заменяется на настоящее имя файла
    • directory — директория, в которую будет загружен файл
    • autoUpload — true\false — начинать ли аплоад сразу после выбора файла
    • onSelect — функция, в которую передается объект, который в данный момент я и описываю) Вызывается в тот момент, когда был выбран файл
    • onStart — функция, которая вызывается, когда стартавал аплоад файла
    • onComplete — также функция. Вызывается в тот момент, когда загрузка файла завершена. Принимает в качестве параметра объект, содержащий ключи path (путь до файла на сервере), size (размер в байтах), name (имя файла)
PHP код файла upload.php, который и аплоадит и показывает прогресс аплоада:

  1. <?php
  2. function uploadFile()
  3. {
  4.   if (sizeof($_FILES))
  5.   {
  6.     $dir = getDir();
  7.     if ($dir !='' && !is_dir($dir))
  8.       mkdir($dir);
  9.     foreach($_FILES as $file)
  10.     {
  11.       $filename = str_replace('%real%', $file['name'], $_POST[$_POST['inputName'].'_serverFileName_def']);
  12.       move_uploaded_file($file['tmp_name'], $dir."/".$filename);
  13.     }
  14.   }
  15. }
  16.  
  17. function getDir()
  18. {
  19.   $dir = '';
  20.   if ($_POST[$_POST['inputName'].'_directory'] !='') $dir = $_POST[$_POST['inputName'].'_directory'];
  21.   return $dir;
  22. }
  23.  
  24. function progress()
  25. {
  26.   if (!isset($_POST['file'])) die();
  27.   $filename = $_POST['file'];
  28.   if (function_exists("uploadprogress_get_info"))
  29.   {
  30.     $r = uploadprogress_get_info($_POST['key']);
  31.     if (is_array($r))
  32.       $r = array_merge($r,array("result"=>1));
  33.     else
  34.     {
  35.       $size = 0;
  36.       if (file_exists($_POST['file'])) $size = filesize($_POST['file']);
  37.       $r = array("result" => -1, "size"=> $size);
  38.     }
  39.     echo json_encode($r);
  40.   }
  41.   else
  42.   {
  43.     $size = 0;
  44.     if (file_exists($_POST['file'])) $size = filesize($_POST['file']);
  45.     echo json_encode(array("result" => 0,"size" => $size));
  46.   }
  47. }
  48. if (isset($_GET['action']))
  49. {
  50.   if($_GET['action'] == 'uploadFile') uploadFile();
  51.   elseif ($_GET['action'] == 'progress') progress();
  52. }
  53. ?>
* This source code was highlighted with Source Code Highlighter.


Ну. пока вроде все. Спасибо всем за внимание )



Спасибо всем за карму! Перес в jquery.

Внимание тем кто уже загружал плагин! jquery.form.js и upload.php изменены. Добавлена мультизагрузка и исправлен один баг!

Плагин уже используется в личном кабинете компании СМС услуги, работает там ишачком на нужды клиентов, заливающих excel-файлы с базами абонентов для последующих смс рассылок. =) В числе клиентов куча офисных работников с IE самых разных видов, ни у кого проблем при аплоаде не возникает. Пользуйтесь ;)

Так как хостинг, держащий эти файлы пропал, выкладываю код плагина здесь, демка пропала без вести ) Не забудьте подключить jQuery и jQuery UI!

jQuery.form = {<br>    set:function(form,name,values)<br>    {<br>        var selector = "."+form+"[name="+name+"]";<br>        if ($(selector).is(':checkbox'))<br>        {<br>            if (!$.isArray(values)) values = new Array(values);<br>            $(selector).removeAttr("checked");<br>            for (var i = 0; i < values.length; i++)<br>                $(selector+"[value='"+values[i]+"']").attr("checked","checked");<br>            return;<br>        }<br>        if ($(selector).is(':radio'))<br>        {<br>            $(selector).removeAttr("checked");<br>            $(selector+"[value='"+values+"']").attr("checked","checked");return;<br>        }<br>        $(selector).val(values);<br>        return;<br>    },<br>    save:function(params)//name,url,key,callback,params,multi<br>    {<br>         var p = {<br>            name:'form',<br>            url:'',<br>            key:null,<br>            test:false,<br>            callback:function(){},<br>            params:{},<br>            multi:false<br>        }<br>        p = $.extend(p,params);<br>        var form = $.form.get(p.name,false,p.multi);<br>        if ( p.key !=null )<br>        {<br>            var c = {};<br>            c[p.key] = form;<br>            form = c;<br>        }<br>        form = $.toJSON(form);<br>        if (p.params == null) p.params = {p:form};<br>        else p.params.p = form;<br>        $.post(p.url,p.params,function(data){<br>            if (p.test)<br>                alert(data);<br>            data = $.parseJSON(data);<br>            if (data.code == 1)<br>                $.form.ok(p.name,data.descr,data.title);<br>            else $.form.error(p.name,data.descr,data.title);<br>            p.callback(data);<br>        },'html');<br>    },<br>    get:function(form,json,multi){<br>        if (multi == null) multi = false;<br>        if (json == null) json = true;<br>        if (form == null || form.length == 0)<br>        {<br>            if (!json) return {};<br>            else return $.toJSON({});<br>        }<br>        var selector = "input."+form+":radio:checked,input."+form+":checkbox:checked,input."+form+":text,input."+form+":hidden,input."+form+":file,input."+form+":password,textarea."+form+",select."+form;<br>        var inputs = $(selector);<br>        var values = {};<br>        $.each(inputs,function(){<br>            var name = $(this).attr("name");<br>            var value = $(this).val();<br>            <br>            if (($.isArray(value) && value[0] == null) || value == null)<br>                return;<br>            if ($(this).is(':file'))<br>            {<br>                var name = $(this).attr("name");<br><br>                var key = $(this).attr("key");<br>                var s = "input[type=hidden][key="+key+"]";            <br>                var v = {};<br>                v.directory = $(s+"[name="+name+"_directory]").attr("value");<br>                v.serverFileName = $(s+"[name="+name+"_serverFileName]").attr("value");<br>                v.path = $(s+"[name="+name+"_path]").attr("value");<br>                v.size = $(s+"[name="+name+"_size]").attr("value");<br>                v.isUploaded = $(s+"[name="+name+"_isUploaded]").attr("value");<br>                if (v.isUploaded == false || v.isUploaded == 0 || v.isUploaded == "0") return;<br>                if (!multi && !$.form.intervals[key].wasMulti) values[name] = v;<br>                else<br>                {<br>                    if (values[name] == null) values[name] = new Array();<br>                    values[name][values[name].length] = v;<br>                }<br>                return;<br>            }<br>            if (multi || $(this).is(':checkbox'))<br>            {<br>                if ($(this).is(":checkbox") && !$(this).attr("checked")) return;<br>                if (values[name] == null) values[name] = new Array();<br>                values[name][values[name].length] = value;<br>            }<br>            else<br>            {<br>                values[name] = value;<br>            }<br>        });<br><br>        if (json == false)<br>            return values;<br>        else<br>            return $.toJSON(values);<br>    },<br>    addInputFile:function(form,name,container)<br>    {<br>        var key = $('.'+form+'[name='+name+']').attr("key");<br><br>        var p = {};<br>        var oldparams = $.form.intervals[key];<br>        p.upload = oldparams.upload;<br>        p.progress = oldparams.progress;<br>        p.serverFileName = oldparams.serverFileName_def;<br>        p.directory = oldparams.directory;<br>        p.autoUpload = oldparams.autoUpload;<br>        p.multi = false;<br>        p.wasMulti = oldparams.wasMulti;<br>        p.onSelect = oldparams.onSelect;<br>        p.onStart = oldparams.onStart;<br>        p.onComplete = oldparams.onComplete;<br><br>        $(container).append("<input type=file name="+name+" class="+form+">");<br>        $.form.makeUpload('.'+form+'[name='+name+']',p,'multi');<br>    },<br>    uploadChange:function(key,param,value){<br>        $("input[key='"+key+"'][name='"+param+"']").attr("value",value);<br>    },<br>    makeUpload: function (selector,params,add){<br><br>        var elements = $(selector);<br>        $.each(elements,function(){<br>            var p = {<br>                upload:"/upload.php?action=uploadFile",<br>                progress:"/upload.php?action=progress",<br>                serverFileName:"%real%",<br>                directory:"",<br>                userParam:"",<br>                autoUpload:false,<br>                multi:false,<br>                wasMulti:false,<br>                onSelect:function(){},<br>                onStart:function(){},<br>                onComplete:function(){},<br>                name:$(selector).attr("name")<br>            }<br>            if ($(this).attr("key")!=null) return;<br>            var date = new Date();<br>            var key = date.getMilliseconds().toString()+date.getMinutes().toString()+date.getSeconds().toString()+Math.round(Math.random()*(1000000 - 0)).toString();<br>            p = $.extend(p,params);<br>            if (add == null)<br>                p.wasMulti = p.multi;<br>            else (p.wasMulti = true);<br>            p.selector = "[type=file][key="+key+"]";<br>            p.key = key;<br>            p.serverFileName_def = p.serverFileName;<br>            $(this).attr("key",key).change(function(){<br>                if ($("#submit_"+key).length == 0)<br>                {<br>                    $.form.intervals[key].onSelect($.form.intervals[key]);<br>                    $(this).after("<input type=submit value='Загрузить' id=submit_"+key+">");<br>                    if ($.form.intervals[key].autoUpload == true)<br>                        $("#submit_"+key).click();<br>                }<br>            });<br>            $(this).wrap("<form key='"+key+"' onsubmit=\"return $.form.uploadSelectedFile(this)\" name=wfUpload_"+key+" action='"+p.upload+"' target=iframe_"+key+" enctype='multipart/form-data' method=post></form>")<br>            $(this).parent().append("<input type=hidden name=key value='"+key+"'>");<br>            $(this).before('<input type="hidden" name="UPLOAD_IDENTIFIER" value="'+key+'">');<br>            var span = $(this).parent();<br>            var html =<br>                "<input type=hidden name='"+p.name+"_directory' key='"+key+"' value='"+p.directory+"'>" +<br>                "<input type=hidden name='"+p.name+"_serverFileName' key='"+key+"' value='"+p.serverFileName+"'>" +<br>                "<input type=hidden name='"+p.name+"_serverFileName_def' key='"+key+"' value='"+p.serverFileName_def+"'>" +<br>                "<input type=hidden name='"+p.name+"_path' key='"+key+"' value=''>" +<br>                "<input type=hidden name='inputName' key='"+key+"' value='"+p.name+"'>" +<br>                "<input type=hidden name='userParam' key='"+key+"' value='"+p.userParam+"'>" +<br>                "<input type=hidden name='"+p.name+"_isUploaded' key='"+key+"' value='0'>" +<br>                "<input type=hidden name='"+p.name+"_size' key='"+key+"' value=''>" +<br>                "<span uploaded=0 class=uploadDescr style='display:none' key='"+key+"'></span>" +<br>                "<iframe style='display:none;' onLoad=$.form.uploadComplete('"+key+"') name=iframe_"+key+" id=iframe_"+key+"></iframe>";<br>            $(span).append(html);<br>            if ($.form.intervals[key] == null)<br>                $.form.intervals[key] = p;<br>        });<br>        if (params.multi == true)<br>        {<br>            var l = elements.length;<br>            if (l > 0 && $('#more_files_'+$(elements[l-1]).attr("key")).length == 0)<br>                $(elements[l-1]).parent('form').after("<br><input type=submit value='Добавить еще один файл' onclick=$.form.addInputFile('"+$(elements[l-1]).attr("class")+"','"+$(elements[l-1]).attr("name")+"','#more_files_"+$(elements[l-1]).attr("key")+"')><br>").after('<span id=more_files_'+$(elements[l-1]).attr("key")+'></span>');<br>        }<br>    },<br>    uploadSelectedFile: function(s,params)<br>    {<br>        var p = {<br>            width:100,<br>            height:15<br>        }<br>        p = $.extend(p,params);<br>        var key = $(s).attr("key");<br>        $("#submit_"+key).attr("disabled","disabled");<br>        var span = $(s).children(".uploadDescr");<br>        var style = {display:'none', margin:"10px"};<br>        $(span).html("<div class=progressbar></div> <span style='text-align:right;' class=uploadedFileDetailInfo>Загрузка началась. Пожалуйста, подождите...</span>").css(style);<br>        var bar = $(span).children('div.progressbar');<br>        bar.progressbar({value: 0});<br>        //alert($.form.intervals[key].selector);<br>        var fname = $($.form.intervals[key].selector).attr("value");<br>        fname = fname.split('\\');<br>        $.form.intervals[key].realFileName = fname[fname.length-1];<br>        $.form.intervals[key].key = key;<br>        $.form.intervals[key].bar = bar;<br>        $.form.intervals[key].span = span;<br>        $($.form.intervals[key].span).attr("uploaded",0);<br>        $.form.intervals[key].onStart($.form.intervals[key]);<br>        //$.form.uploadProgress(key);<br>        $.form.intervals[key].interval = setInterval('$.form.uploadProgress("'+key+'")',1000);<br>    },<br>    uploadProgress: function(key){<br>        $.ajax({<br>            error:function(XMLHttpRequest, textStatus, errorThrown) {<br>            },<br>            start:function(){},<br>            beforeSend:function ( request ) {<br>                request.setRequestHeader( 'Cookie', document.cookie );<br>            },<br>            url:$.form.intervals[key].progress,<br>            data:{<br>                key:key,<br>                file:$.form.intervals[key].directory+"/"+$.form.intervals[key].realFileName<br>            },<br>            complete:function(){},<br>            dataType:'html',<br>            type:'post',<br>            success:function(data){<br>                data = $.parseJSON(data);<br>                if (data.result == 1)<br>                {<br>                    var timelast=data.time_last;<br>                    var total = data.bytes_total;<br>                    var speed = data.speed_average;<br>                    var bytes = data.bytes_uploaded;<br>                    var eta = data.est_sec;<br>                    var min = Math.round(eta / 60);<br>                    var sec = eta - min*60;<br>                    if(min==0){var time=sec+" сек."}else{var time=min+" мин."+sec+" сек."}<br>                    var speeds = $.form.speeds(speed);<br>                    var percents = Math.round(bytes * 100 / total);<br>                    $.form.intervals[key].size = total;<br>                    $($.form.intervals[key].span).children('.uploadedFileDetailInfo').html("<b>"+percents+"%</b>, <i>скорость:</i> <b>"+speeds+"</b>, <i>загружено</i> <b>"+$.form.fsize(bytes)+"</b> <i>из</i> <b>"+$.form.fsize(total)+"</b>");<br>                    $.form.intervals[key].bar.progressbar('value',percents);<br>                }<br>                if (data.result == -1 )<br>                    $.form.intervals[key].size = data.size;<br>                if (data.result == 0)<br>                {<br>                    $.form.intervals[key].size = data.size;<br>                    //alert(data.size);<br>                    if ($($.form.intervals[key].span).attr("uploaded") == 0)<br>                        $($.form.intervals[key].span).html("Сервер не поддерживает отображение процесса загрузки. Подождите завершения загрузки файла...");<br>                }<br><br>                $($.form.intervals[key].span).slideDown();<br>        }});<br>    },<br>    uploadCompleteAfterTimer:function(key){<br>        if ($.form.intervals[key].realFileName == null ) return;<br>        clearInterval($.form.intervals[key].interval);<br>        var size = "false";<br>        if ($.form.intervals[key].size != null) size = $.form.intervals[key].size;<br>        var serverFileName = $.form.str_replace('%real%',$.form.intervals[key].realFileName,$.form.intervals[key].serverFileName);<br>        var value = $.form.intervals[key].directory+"/"+serverFileName;<br>        $("input[key="+key+"][name="+$.form.intervals[key].name+"_path]").attr("value",value);<br>        $("input[key="+key+"][name="+$.form.intervals[key].name+"_isUploaded]").attr("value",1);<br>        $("input[key="+key+"][name="+$.form.intervals[key].name+"_size]").attr("value",size);<br>        $("input[key="+key+"][name="+$.form.intervals[key].name+"_serverFileName]").attr("value",serverFileName);<br>        $($.form.intervals[key].span).attr("uploaded",1);<br>        $("#submit_"+key).remove();<br>        $(".uploadDescr[key="+key+"]").html("Загрузка завершена!!!");<br>        var opt = {<br>            path:value,<br>            size:size,<br>            name:$.form.intervals[key].realFileName<br>        };<br>        $.form.intervals[key].onComplete(opt);<br>    },<br>    uploadComplete:function(key){<br>            setTimeout("$.form.uploadCompleteAfterTimer('"+key+"')",500);<br>    },<br>    intervals:{},<br>    "fsize":function(x) {<br>        x = Math.round(x / 1024);<br>        if (x < 1000) {<br>            return x + " " + "Кб";<br>        }<br>        x = Math.round(x * 100 / 1024) / 100;<br>        return x + " " + "Мб";<br>    },<br>    "speeds":function (x) {<br>        x = Math.round(x / 1024);<br>        if (x < 1000) {<br>            return x + " " + "Кб/сек";<br>        }<br>        x = Math.round(x * 100 / 1024) / 100;<br>        return x + " " + "Мб/сек";<br>    },<br>    "str_replace":function (search, replace, subject, count) {<br>        var i = 0, j = 0, temp = '', repl = '', sl = 0, fl = 0,<br>                f = [].concat(search),<br>                r = [].concat(replace),<br>                s = subject,<br>                ra = r instanceof Array, sa = s instanceof Array;<br>        s = [].concat(s);<br>        if (count) {<br>            this.window[count] = 0;<br>        }<br><br>        for (i=0, sl=s.length; i < sl; i++) {<br>            if (s[i] === '') {<br>                continue;<br>            }<br>            for (j=0, fl=f.length; j < fl; j++) {<br>                temp = s[i]+'';<br>                repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];<br>                s[i] = (temp).split(f[j]).join(repl);<br>                if (count && s[i] !== temp) {<br>                    this.window[count] += (temp.length-s[i].length)/f[j].length;}<br>            }<br>        }<br>        return sa ? s : s[0];<br>    }<br>}<br><br>* This source code was highlighted with Source Code Highlighter.
Резник Артем @DarthRaven
карма
41,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (98)

  • +1
    А что, файл нельзя отправить?
    • +1
      Так, а вот по этому поводу у меня есть следующая статья про, опять же, самописный jQuery плагин, служащий для ajax-upload`а файлов. Пока что анонс — для его работы не требуется Flash, только jquery + php. Если сервер поддерживает функцию uploadprogress_get_info, то включается и progress bar. Если функция отстутсвует в Вашей сборки, прогресс загрузки файла не будет отображаться.
      В скором будущем — обязательно напишу о нем.
      • +1
        Может лучше не flash, а iframe?
        • +1
          Так я и говорю, что "для его работы не требуется Flash". То есть совсем ) Загрузчик как раз на iframe и работает )
      • 0
        Интересно, на многих shared-хотингах поддерживается uploadprogress_get_info? Я, например, про такую функцию первый раз слышу. Ведь вся прелесть данного загрузчика именно в прогресс-баре.
        • +1
          А Flash частенько глючит и тормозит на линухах. Я так с ним намаялся на убунте, что решил, что такую проблему легче один раз решить на сервере, чем маяться с несовместимостью у каждого клиента.
        • 0
          uploadprogress_get_info — очень редко, где есть, да и работает эта функция ТОЛЬКО на РНР 5.3
      • 0
        uploadprogress обображает прогресс для всех файлов сразу. А решение на flash'е может показать прогресс по каждому файлу и в целом.
        • 0
          Нет, не для всех. Ему методом POST передается уникальный идентификатор аплоада, и показывается статистика только по этой загрузке.
          • 0
            ок. У меня есть форма и количество прикрепляемых файлов может варьироваться. Хочу видеть статистику/прогресс загрузки по каждому из файлов и в целом.
            • 0
              Сорри, не прочел с первого раза «и в целом». Да, так, конечно, не получится.
    • +3
      Updated: загрузчик файлов добавлен )
  • +1
    И правда, как дела с type=«file»?
    • 0
      Ответ выше )
  • +1
    Не, ну правильно же? Если делать — то до конца!!!
    • 0
      Просто эйфория и желание скорее запостить первый топик ) Прошу извинить ;) Исправимся.
      • 0
        Да ничё, я тоже чудил!!! ))
  • +2
    Не забываем про существование замечательного плагин jQuery Form ( jquery.malsup.com/form/ ), который поддерживает асинхронную закачку файлов и прочие вкусности.
    • +1
      Обязательно ознакомлюсь с ним ) Но сразу могу сказать, что uploader там не такой вкусный )
      • 0
        да при загрузке фалов был баг в опера 10, пробовал на версии jquery.form 2.28, файлы больше 1,5 мб не загружались или грузились через раз, а если загружал изображения и ещё их резал, то 100% обрубало загрузку, во всех остальных браузерах всё схватывало отлично
  • +3
    Получение всех данных из формы — $(«id»).serialize()
    • 0
      Да, с этой функцией знаком, но соль в том, что хотелось получать объект, и как-то манипулировать им перед отправкой на сервер.
      • +1
        serializeArray() возвращает массив объектов {name:'email',value:'xxx@xxx.xxx'}. Перебрать его в объект нужного вида не должно составлять труда. И манипулируйте на здоровье.
        • –4
          И эту функцию тоже видел ) Но хотелось все же просто ключ: значения. В целом, конечно, на вкус и цвет )
  • +1
    Тоже не так давно писал загрузчик/сабмиттер форм ( bitbucket.org/kmike/gearsuploader/ ), для работы нужен Google Gears (+mootools), если его нет — делается fall-back на обычную отправку форм. Умеет пережимать картинки на клиенте, показывать прогресс-бар при загрузке файла (изменения на серверной части не нужны), в качестве плюшки сделана интеграция с джанговскими формсетами (что позволяет делать массовую загрузку картинок с ресайзом на клиенте, не меняя код на сервере — используя там обычные formset'ы).

    Но все пока не супер-продакшн качества. В ИЕ вроде не работает прогресс-бар, нужно смотреть. Кому интересно, можете потестировать. В репозитории есть пример django-проекта, хорошо бы еще php сделать) Тоже хотел про все это написать сюда на хабр с подробными инструкциями и примерами, но руки пока не доходят.
    • +1
      да, немного документации: bitbucket.org/kmike/gearsuploader/wiki/ru
    • 0
      С ишаком действительно всегда много мороки. Я в своем загрузчике вроде поборол все его реинкарнации )
      >>>Умеет пережимать картинки на клиенте
      Не подскажете, этот функционал обеспечивается Google Gears, или чем-то другим?
      • 0
        Да, Gears'ом. Из-за этого функционала все и затевалось, по сути. Остальное (загрузка обычных файлов, отправка форм) — побочные эффекты.
        • 0
          Пожалуй стоит с этой либой поплотнее познокомиться…
  • +1
    молодцом, смотрится на 5.
    • 0
      спасибо )
  • +1
    Спасибо большое, именно это я и искал!
    • +1
      не за что ) Очень приятно.
  • 0
    В целом мне и обычный плагин форм нравится. У меня к нему свой класс на PHP написан. Сейчас еще со Smarty его пытаюсь подружить.
    Но вот загрузчик файлов я себе позаимствую, немного переработав, если вы не против =))
    • 0
      Для того и выкладывал ) Удачи вам разобраться с немножко сумбурным кодом загрузчика ) Хотя я его сегодня уже причесал немного) Заранее прошу прощения за отсутствие комментариев )
    • 0
      Кстати, насчет PHP класса для плагина )
      У меня для CodeIgniter написана модель, помогающая работать с данными, полученными посредством этого плагина. Имеются следующие методы:
      get — получения данных по условию
      set — установить новые значения
      exist — проверить, существуют ли переданные в метод ключи в этом массиве
      delete — удалить указанные ключи
      deleteAllBut — удалить все ключи кроме указанных
      sizeOf — количество ключей в указанном подмассиве
      strlen — получает список ключей, а так же интервал min и max длины строки (можно каждому ключу задать свой интервал). И возвращает true, если все ключи прошли проверку, иначе — false. Так же если передать еще один флажок, то вернет развернутый отчет — true\false по каждому ключу.
      setParams — заменить текущий массив для обработки на новый
      • 0
        У меня формы завязаны на базу. Сначала описывается сама форма:

        <?php
        /**
         * Форма USERS
         */
        $forms->create('users', array(
        
        	'method' => 'post', // метод отправки
        	'action' => '/ajax/xforms/action_users.php', // скрипт обработки
        	'class' => 'standart', // CSS класс
        	'table' => DBUSERS, // таблица БД
        
        	'fields' => array(
        
        			'id' => array( 'type' => 'hidden' ),
        
        			'email' => array( 'type' => 'text', 'label' => 'Email', 'notice' => 'необходим для авторизации' ),
        			'password' => array( 'type' => 'password', 'label' => 'Пароль', 'notice' => 'только чтобы изменить' ),
        
        			'solt' => array( 'type' => 'hidden' ),
        			'kod' => array( 'type' => 'hidden' ),
        
        			'fname' => array( 'type' => 'text', 'label' => 'Фамилия' ),
        			'lname' => array( 'type' => 'text', 'label' => '* Имя'/*, 'obligatory' => 1*/ ),
        			'tname' => array( 'type' => 'text', 'label' => 'Отчество' ),
        
        			'phone1' => array( 'type' => 'text', 'label' => 'Телефон' ),
        			'phone2' => array( 'type' => 'text', 'label' => 'Факс' ),
        			'phone3' => array( 'type' => 'text', 'label' => 'Мобильный' ),
        
        			'firm_value' => array( // no DB
        				'type' => 'suggest', 
        				'label' => '* Фирма',
        				'ajax' => '/ajax/suggest/sug_users_firms.php',
        				'field_value' => 'firm',
        			),
        			'firm' => array( 'type'=>'hidden' ),
        			
        			'contr_value' => array( // no DB
        				'type' => 'suggest', 
        				'label' => 'Контрагент',
        				'ajax' => '/ajax/suggest/sug_users_contr.php',
        				'field_value' => 'contractor',
        			),
        			'contractor' => array( 'type' => 'hidden' ),
        			
        			'position' => array( 'type' => 'text', 'label' => 'Должность' ), // должность
        			'otdel' => array( 'type' => 'text', 'label' => 'Отдел' ),
        			'other' => array( 'type' => 'textarea', 'label' => 'Дополнительно' ),
        
        			'date' => array( 'type' => 'hidden' ),
        			'last_date' => array( 'type' => 'hidden' ),
        			'ip' => array( 'type' => 'hidden' ),
        			'fix_ip' => array( 'type' => 'hidden' ),
        			'status' => array( 'type' => 'hidden', 'label' => '' ),
        
        			'submit' => array( 'type' => 'submit', 'value' => 'Сохранить' ),
        
        	),
        ));
        ?>
        


        Поля, соответствующие таблице могут писаться в базу. В соответствии с ним происходит обработка в JS при вводе информации в фронтэнде и при сохранении в бакенде. отправка происходит через формы JQuery, если включен JS или как обычно, если выключен.
        Есть реализация интеграции с Jquery-UI.

        Так еще доступны типы int, float, select, radio и некоторые другие.

        Сейчас доступны методы:

        create() — создание формы (см. выше)
        getForm( 'formname' ) — вернет описание формы, как массив выше
        clear() — очистит значения value у полей
        getPost() — дёрнет из поста соответствующие полям индексы (нужно, когда считывает отправленные данные, этот же метод производит чистку данных по типам)
        setTable() — сохранит данные в таблицу БД
        getTable() — загрузит данные из таблицы БД

        getValue() — получить значение поля
        getValues() — получить значения всех полей
        setValue() — установить значение поля
        setValues() — установить значения всех полей

        setVariants() — установить варианты для полей select, radio и checkbox (порой надо, чтобы эти значения заполнялись динамически из базы, например)

        write() — распечатает форму в автоматическом режиме (есть несколько вариантов)

        setReadonly() — утановить поле в readonly (также может отменить readonly)
        setRaedonlyAll() — установить все поля в readonly (также может отменить readonly)
        setHidden() — делает некоторые поля скрытыми/не скрытыми
        setTypes() — можно для некоторых полей поменять тип

        Как-то так.
  • 0
    Из селекта созвращаются только названия полей, а их values нет.
    • 0
      Простите, не посмотрел код.
      • 0
        Ага, значения полей тоже русские)
  • +2
    У вас много «зашитого» html кода внутри плагина — это не найс (например: «Загрузка началась. Пожалуйста, подождите...», там много такого). Можно все служебные тексты в отдельный json кусочек вынести. Я бы вообще не писал своих текстов а вызывал пользовательские функции, которые бы писали текст, если нужно.
    • +1
      часто делают объект settings с настройками по умолчанию, а потом делают его extend
    • 0
      Да, я уже тоже подумываю о выносе всех языковых строк в настройки, для мультиязычности ) Это тоже обязательно будет сделано.
  • 0
    мне вот интересно а как получить скорость передачи файла?
    • +1
      размер файла, деленный на процент переданного, деленный на время?
      • 0
        вы написали че-то не то, я знаю как вычисляется скорость, в данном случаи просто кол-во переданной информации деленное на время, скорость не зависит от размера файла.
        во-вторых, может я неправильно выразился, но мне было интересно как получить кол-во переданной информации в данный момент
        • +1
          чуть выше упоминали uploadprogress_get_info, да и в коде серверной части плагина она упоминается:
          function_exists(«uploadprogress_get_info»)

          можно еще поискать аналоги.
  • +1
    Если не установлено раширение с uploadprogress_get_info, но установлено APC (что встречается), получить количество загруженного контента можно с помощью функции apc_fetch().

    Пример, например, по ссылке
    www.ibm.com/developerworks/library/os-php-v525/index.html
    • 0
      Что ж, достаточно немного модифицировать upload.php )
  • 0
    Расскажите пожалуйста как подключить uploadprogress_get_info
    • 0
      pecl.php.net/package/uploadprogress — вот ссыль на это расширение.
      • 0
        Опишите пожалуйста как его установить. Вещь нужная почти для каждого сайта.
        • 0
          Сам я, когда разрабатывал этот плагин, просил установить uploadprogress нашего админа. Но вот навскидку ссылка:
          andyceo.ruware.com/blog/andyceo/kak-ustanovit-pecl-biblioteku-na-server-ubuntu — как установить pecl-расширение на убунту.
          handynotes.ru/2007/06/pecl-php.html — а это под виндой.
          К сожалению, не смогу вам помочь полноценно =\
          Если не вы админите серв, попробуйте попросить его владельцев поставить это расширение.
          • 0
            Спасибо. Первая ссылка не работает. Хабраэффект ?)
          • 0
            в папке где находится pecl нужно запустить
            ./pecl install uploadprogress
            правда до конца не поставилась через
            ERROR: `phpize' failed
            использую XAMPP
          • 0
  • +1
    Всё красиво, но вот только не хватает возможности выбора и загрузки сразу нескольких файлов
    • 0
      Над множественным выбором обещаю подумать, как лучше реализовать )
      • +1
        Если еще и это реализуешь — цены тебе и твоему плагину не будет
        • 0
          Реализовано! При инициализации makeUpload теперь можно передать еще один параметр multi:true. Демо обновлено
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Уже на вашем сервере не работает, или в демке?
      • НЛО прилетело и опубликовало эту надпись здесь
        • 0
          Ну да, кодировка должна быть utf-8.
          А как именно отрабатывает скрипт? Просто ошибка, или же он все же пишет, что отображение прогресса загрузки не поддерживается сервером?
          • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              Так может быть все же причина в том, что не стоит расширение uploadprogress для php? (http://pecl.php.net/package/uploadprogress)
              • НЛО прилетело и опубликовало эту надпись здесь
                • 0
                  Сообщение о том, что отображение прогресса не поддерживается, может быть вызвано лишь тем, что функция function_exists(«uploadprogress_get_info») возвращает false. Попробуйте в каком-нибудь левом скрипте посмотреть результат выполнения этой функции.
                  • НЛО прилетело и опубликовало эту надпись здесь
                    • 0
                      При таком варианте есть одна проблемка: папка tmp, куда изначально грузятся файлы, не всегда доступна. Все от хостера зависит.
                      • НЛО прилетело и опубликовало эту надпись здесь
                        • 0
                          Только очень уж гудение в комнате досаждает =)
                          • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Плагин обновлен. Добавлена мультизагрузка и исправлен баг при повторной загрузке файла (был неприятный глюк). Необходимо обновить upload.php и jquery.form.js
    • +1
      Молодцом, так быстро и качественно дополнять и исправлять! Ни каждому дано)
  • –1
    Откройте для себя uploadify. Флеш стоит почти у всех.
    • 0
      Я уже выше приводил свои аргументы, почему я против использования flash в аплоадерах.
  • 0
    Вчера невнимательно перезалил обновления плагина, из-за чего весь день демо, оказывается не работало. Теперь fixed )
    • 0
      Сейчас тоже не работает
      • 0
        Оп, сжатие js и css на серваке отказало. Ща отключил его к хренам. Пробуйте ;)
        • 0
          Загружать данные формы и файл одновременно оно умеет?
          Т.е. загрузка не просто файлов, а файлов с описанием, но, условно говоря, в одном запросе?
          • 0
            Можно конечно, располагайте все эти элементы с одинаковым идентификатором формы.
        • 0
          ах да, еще
          что происходит при ошибках загрузки? :)
          • 0
            А вот этот момент, если честно, не продуман )
  • 0
    нету ни демо, ни самого плагина :((
    • 0
      sms-uslugi.ru/habr.rar — временное решение проблемы. Тут демка и скрипт.

      Ща разберусь что с тем адресом случилось.
      • 0
        спасибо :)
  • 0
    это значит так- берем меняем библиотеку с 1.3.1 на 1.4.2 и скрипт радостно дохнет )
    в get не входит вот сюда $.each(inputs,function(){
    — пока не понимаю как пофиксить, но наверно у вас не то что-то с синтаксисом
    • +1
      извиняюсь — это не у вас проблема, а в кривом сборщике моего 1.4.2.min.js была :)
      • 0
        Угу ) У меня тоже с 1.4.2 все нормально робит ;)
        • 0
          Кстати,
          я тут ещё мучался с set пока не понял что в jquery UI надо вызвать после установки ещё и рефреш
          $(«имя»).buttonset(«refresh» );
  • 0
    Добавьте на любой репозитарий, не работает ничего. github.com. У кого есть, отпишитесь пожалуйста.
    • 0
      Удивительно, вы уже второй за сегодня, кто обратился за плагинчиком =)
      Вот временная ссылка на js и php файл — upload.com.ua/get/901687340/
  • 0
    Ни одна ссылка ни не демо ни на плагин не работает.
    Не могли бы Вы демку сбросить на какой нибудь файлообменник.
    В смысле не только те, что скачались с временной ссылке, но и пример использования.
    Спасибо
    • 0
      У меня, к сожалению, не сохранились примеры, я их вместе с хостингом потерял. Так что только скрипты, что по ссылке в комментарии выше, доступны. Прошу прощения
  • 0
    И на том спасибо. Разберемся.
  • 0
    уважаемые, скиньте пожалуйста демку рабочую, у меня не получается работать с этим плагином…
    • 0
      В общем пока разбирался нашел схожее решение только без upload'а файлов.
      Может кому пригодиться — www.linkexchanger.su/2008/45.html

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.