Commits

Bogdan Savluk committed 7a46d42

Added ability for few gallery manager widgets on same page. Moved styles and scripts from view to separate files, added minified script versions.

  • Participants
  • Parent commits 0d2cff0

Comments (0)

Files changed (5)

File GalleryManager.php

     /** Render widget */
     public function run()
     {
+        /** @var $cs CClientScript */
+        $cs = Yii::app()->clientScript;
+        $cs->registerCssFile($this->assets . '/galleryManager.css');
 
-        $cs = Yii::app()->clientScript;
         $cs->registerCoreScript('jquery');
-        $cs->registerScriptFile($this->assets . '/jquery.iframe-transport.min.js');
+        $cs->registerCoreScript('jquery.ui');
+
+        if (defined('YII_DEBUG')) {
+            $cs->registerScriptFile($this->assets . '/jquery.iframe-transport.js');
+            $cs->registerScriptFile($this->assets . '/jquery.galleryManager.js');
+        } else {
+            $cs->registerScriptFile($this->assets . '/jquery.iframe-transport.min.js');
+            $cs->registerScriptFile($this->assets . '/jquery.galleryManager.min.js');
+        }
 
         if ($this->controllerRoute === null)
             throw new CException('$controllerRoute must be set.', 500);
+
+        $opts = CJavaScript::encode(array(
+            'hasName:' => $this->gallery->name ? true : false,
+            'hasDesc:' => $this->gallery->description ? true : false,
+            'uploadUrl' => Yii::app()->createUrl($this->controllerRoute . '/ajaxUpload', array('gallery_id' => $this->gallery->id)),
+            'deleteUrl' => Yii::app()->createUrl($this->controllerRoute . '/delete'),
+            'updateUrl' => Yii::app()->createUrl($this->controllerRoute . '/changeData'),
+            'arrangeUrl' => Yii::app()->createUrl($this->controllerRoute . '/order'),
+            'nameLabel' => Yii::t('galleryManager.main', 'Name'),
+            'descriptionLabel' => Yii::t('galleryManager.main', 'Description'),
+        ));
+        $src = "$('#{$this->id}').galleryManager({$opts});";
+        $cs->registerScript('galleryManager#' . $this->id, $src);
         $model = new GalleryPhoto();
         $this->render('galleryManager', array(
             'model' => $model,

File assets/galleryManager.css

+/* Photo Gallery */
+.GalleryEditor {
+    border: 1px solid #DDD;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+    -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
+    -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
+    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.GalleryEditor div.gform {
+    padding-top: 4px;
+    clear: left;
+}
+
+.GalleryEditor form {
+    margin: 0;
+}
+
+.GalleryEditor .photo {
+    position: relative;
+    float: left;
+    background-color: #fff;
+    margin: 4px;
+    height: 178px;
+    width: 140px;
+
+    display: block;
+    padding: 4px;
+    line-height: 1;
+    border: 1px solid #DDD;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+    -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
+    -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
+    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.GalleryEditor .photo img {
+    width: 140px;
+    height: auto;
+}
+
+.GalleryEditor .photo a {
+    padding-left: 8px;
+}
+
+.GalleryEditor .photo .actions {
+    float: right;
+
+    position: absolute;
+    bottom: 4px;
+    right: 4px;
+}
+
+.GalleryEditor hr {
+    margin: 0 4px;
+}
+
+.GalleryEditor .fileinput-button {
+    position: relative;
+    overflow: hidden;
+    margin-left: 8px;
+    margin-top: 4px;
+    margin-bottom: 4px;
+}
+
+.GalleryEditor .fileinput-button input {
+    position: absolute;
+    top: 0;
+    right: 0;
+    margin: 0;
+    border: solid transparent;
+    border-width: 0 0 100px 200px;
+    opacity: 0;
+    filter: alpha(opacity = 0);
+    -moz-transform: translate(-300px, 0) scale(4);
+    direction: ltr;
+    cursor: pointer;
+}
+
+/* modal styles*/
+.GalleryEditor .preview {
+    overflow: hidden;
+    width: 200px;
+    height: 156px;
+    margin-right: 10px;
+    overflow: hidden;
+    float: left;
+}
+
+.GalleryEditor .preview img {
+    width: 200px;
+}
+
+.GalleryEditor .photo-editor {
+    min-height: 156px;
+    margin-bottom: 4px;
+    padding: 4px;
+    border: 1px solid #DDD;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+    -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
+    -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
+    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.photo-editor form {
+    margin-bottom: 0;
+}
+
+.GalleryEditor .caption p {
+    height: 40px;
+    overflow: hidden;
+}
+
+/* fixed thumbnail sizes */
+.GalleryEditor.no-desc .photo {
+    height: 138px;
+}
+
+.GalleryEditor.no-name .photo {
+    height: 160px;
+}
+
+.GalleryEditor.no-name-no-desc .photo {
+    height: 120px;
+}
+
+.GalleryEditor .image-preview {
+    height: 88px;
+    overflow: hidden;
+}
+
+/* item selection */
+.GalleryEditor .photo-select {
+    position: absolute;
+    bottom: 8px;
+    left: 8px;
+}
+
+.GalleryEditor .photo.selected {
+    background-color: #cef;
+    border-color: blue;
+}

File assets/jquery.galleryManager.js

+(function ($) {
+
+    function galleryManager(el, options) {
+        //Defaults:
+        this.defaults = {
+            nameLabel:'Name',
+            descriptionLabel:'Description',
+
+            hasName:true,
+            hasDesc:true,
+
+            uploadUrl:'',
+            deleteUrl:'',
+            updateUrl:'',
+            arrangeUrl:''
+        };
+
+        //Extending options:
+        var opts = $.extend({}, this.defaults, options);
+        //code
+        var $gallery = $(el);
+        opts.wId = $gallery.attr('id');
+
+        var $sorter = $('.sorter', $gallery);
+        var $images = $('.images', $sorter);
+        var $editorModal = $('.editor-modal', $gallery);
+        var $editorForm = $('.form', $editorModal);
+
+
+        function photoEditorTemplate(id, src, name, description) {
+            return '<div class="photo-editor">' +
+                '<div class="preview"><img src="' + src + '" alt=""/></div>' +
+                '<div>' +
+                (opts.hasName
+                    ? '<label for="photo_name_' + id + '">' + opts.nameLabel + ':</label>' +
+                    '<input type="text" name="photo[' + id + '][name]" class="input-xlarge" value="' + name + '" id="photo_name_' + id + '"/>'
+                    : '') +
+                (opts.hasDesc
+                    ? '<label for="photo_description_' + id + '">' + opts.descriptionLabel + ':</label>' +
+                    '<textarea name="photo[' + id + '][description]" rows="3" cols="40" class="input-xlarge" id="photo_description_' + id + '">' + description + '</textarea>'
+                    : '') +
+                '</div>' +
+                '</div>';
+        }
+
+        function photoTemplate(id, src, name, description, rank) {
+            var res = '<div id="' + opts.wId + '-' + id + '" class="photo">' +
+                '<div class="image-preview"><img src="' + src + '"/></div><div class="caption">';
+            if (opts.hasName)res += '<h5>' + name + '</h5>';
+            if (opts.hasDesc)res += '<p>' + description + '</p>';
+            res += '</div><input type="hidden" name="order[' + id + ']" value="' + rank + '"/><div class="actions">' +
+
+                ((opts.hasName || opts.hasDesc)
+                    ? '<span data-photo-id="' + id + '" class="editPhoto btn btn-primary"><i class="icon-edit icon-white"></i></span> '
+                    : '') +
+                '<span data-photo-id="' + id + '" class="deletePhoto btn btn-danger"><i class="icon-remove icon-white"></i></span>' +
+                '</div><input type="checkbox" class="photo-select"/></div>';
+            return res;
+        }
+
+        function deleteClick(e) {
+            e.preventDefault();
+            var id = $(this).data('photo-id');
+            //if (!confirm(deleteConfirmation)) return false;
+            $.ajax({
+                type:'POST',
+                url:opts.deleteUrl,
+                data:'id=' + id,
+                success:function (t) {
+                    if (t == 'OK') $('#' + opts.wId + '-' + id).remove();
+                    else alert(t);
+                }});
+            return false;
+        }
+
+        function editClick(e) {
+            e.preventDefault();
+            var id = $(this).data('photo-id');
+            var photo = $(this).parents('.photo');
+            var src = $('img', photo[0]).attr('src');
+            var name = $('.caption h5', photo[0]).text();
+            var description = $('.caption p', photo[0]).text();
+            $editorForm.html(photoEditorTemplate(id, src, name, description));
+            $editorModal.modal('show');
+            return false;
+        }
+
+        function updateButtons() {
+            var selectedCount = $('.photo.selected', $sorter).length;
+            $('.select_all', $gallery).prop('checked', $('.photo', $sorter).length == selectedCount);
+            if (selectedCount == 0) {
+                $('.edit_selected, .remove_selected', $gallery).addClass('disabled');
+            } else {
+                $('.edit_selected, .remove_selected', $gallery).removeClass('disabled');
+            }
+        }
+
+        function selectChanged() {
+            var $this = $(this);
+            if ($this.is(':checked'))
+                $this.parent().addClass('selected');
+            else
+                $this.parent().removeClass('selected');
+            updateButtons();
+        }
+
+        function bindPhotoEvents(newOne) {
+            $('.deletePhoto', newOne).click(deleteClick);
+            $('.editPhoto', newOne).click(editClick);
+            $('.photo-select', newOne).change(selectChanged);
+        }
+
+        bindPhotoEvents($('.photo', $gallery));
+
+        $('.images', $sorter).sortable().disableSelection().bind("sortstop", function () {
+            $.post(opts.arrangeUrl, $('input', $sorter).serialize() + '&ajax=true', function () {
+                // order saved!
+            }, 'json');
+        });
+
+
+        if (typeof window.FormData == 'function') {  // if XHR2 available
+            $('.afile', $gallery).attr('multiple', 'true').on('change', function (e) {
+                e.preventDefault();
+                var filesCount = this.files.length;
+                var uploadedCount = 0;
+                $editorForm.html('');
+
+                for (var i = 0; i < filesCount; i++) {
+                    var fd = new FormData();
+                    fd.append(this.name, this.files[i]);
+                    var xhr = new XMLHttpRequest();
+                    xhr.open('POST', opts.uploadUrl, true);
+                    xhr.onload = function () {
+                        uploadedCount++;
+                        if (this.status == 200) {
+                            var resp = JSON.parse(this.response);
+                            var newOne = $(photoTemplate(resp['id'], resp['preview'], resp['name'], resp['description'], resp['rank']));
+
+                            bindPhotoEvents(newOne);
+
+                            $images.append(newOne);
+                            if (opts.hasName || opts.hasDesc)
+                                $editorForm.append($(photoEditorTemplate(resp['id'], resp['preview'], resp['name'], resp['description'])));
+                        }
+                        if (uploadedCount === filesCount && (opts.hasName || opts.hasDesc)) $editorModal.modal('show');
+                    };
+                    xhr.send(fd);
+                }
+            });
+        } else {
+            $('.afile', $gallery).on('change', function (e) {
+
+                e.preventDefault();
+                $editorForm.html('');
+
+                $.ajax(
+                    opts.uploadUrl, {
+                        files:$(this),
+                        iframe:true,
+                        dataType:"json"
+                    }).done(function (resp) {
+                        var newOne = $(photoTemplate(resp['id'], resp['preview'], resp['name'], resp['description'], resp['rank']));
+                        bindPhotoEvents(newOne);
+                        $images.append(newOne);
+                        if (opts.hasName || opts.hasDesc)
+                            $editorForm.append($(photoEditorTemplate(resp['id'], resp['preview'], resp['name'], resp['description'])));
+
+                        if (opts.hasName || opts.hasDesc) $editorModal.modal('show');
+                    });
+
+
+            });
+        }
+
+        $('.save-changes', $editorModal).click(function (e) {
+            e.preventDefault();
+            $.post(opts.updateUrl, $('input, textarea', $editorForm).serialize() + '&ajax=true', function (data) {
+                var count = data.length;
+                for (var key = 0; key < count; key++) {
+                    var p = data[key];
+                    var photo = $('#' + opts.wId + '-' + p.id);
+                    $('img', photo).attr('src', p['src']);
+                    if (opts.hasName)
+                        $('.caption h5', photo).text(p['name']);
+                    if (opts.hasDesc)
+                        $('.caption p', photo).text(p['description']);
+                }
+                $editorModal.modal('hide');
+                //deselect all items after editing
+                $('.photo.selected', $sorter).each(function () {
+                    $('.photo-select', this).prop('checked', false)
+                }).removeClass('selected');
+                $('.select_all', $gallery).prop('checked', false);
+                updateButtons();
+            }, 'json');
+
+        });
+
+        $('.edit_selected', $gallery).click(function (e) {
+            e.preventDefault();
+            var cc = 0;
+            var form = $editorForm.html('');
+            $('.photo.selected', $sorter).each(function () {
+                cc++;
+                var photo = $(this),
+                    id = photo.attr('id').substr((opts.wId + '-').length),
+                    src = $('img', photo[0]).attr('src'),
+                    name = $('.caption h5', photo[0]).text(),
+                    description = $('.caption p', photo[0]).text();
+                form.append(photoEditorTemplate(id, src, name, description));
+            });
+            if (cc > 0)$editorModal.modal('show');
+            return false;
+        });
+
+        $('.remove_selected', $gallery).click(function (e) {
+            e.preventDefault();
+            $('.photo.selected', $sorter).each(function () {
+                var id = $(this).attr('id').substr((opts.wId + '-').length);
+                $.ajax({
+                    type:'POST',
+                    url:opts.deleteUrl,
+                    data:'id=' + id,
+                    success:function (t) {
+                        if (t == 'OK') $('#' + opts.wId + '-' + id).remove();
+                        else alert(t);
+                    }});
+            });
+        });
+
+        $('.select_all', $gallery).change(function () {
+            if ($(this).prop('checked')) {
+                $('.photo', $sorter).each(function () {
+                    $('.photo-select', this).prop('checked', true)
+                }).addClass('selected');
+            } else {
+                $('.photo.selected', $sorter).each(function () {
+                    $('.photo-select', this).prop('checked', false)
+                }).removeClass('selected');
+            }
+            updateButtons();
+        });
+    }
+
+    // The actual plugin
+    $.fn.galleryManager = function (options) {
+        if (this.length) {
+            this.each(function () {
+                galleryManager(this, options);
+            });
+        }
+    };
+})(jQuery);

File assets/jquery.galleryManager.min.js

+(function(a){function b(b,c){function j(a,b,c,e){return'<div class="photo-editor"><div class="preview"><img src="'+b+'" alt=""/></div>'+"<div>"+(d.hasName?'<label for="photo_name_'+a+'">'+d.nameLabel+":</label>"+'<input type="text" name="photo['+a+'][name]" class="input-xlarge" value="'+c+'" id="photo_name_'+a+'"/>':"")+(d.hasDesc?'<label for="photo_description_'+a+'">'+d.descriptionLabel+":</label>"+'<textarea name="photo['+a+'][description]" rows="3" cols="40" class="input-xlarge" id="photo_description_'+a+'">'+e+"</textarea>":"")+"</div>"+"</div>"}function k(a,b,c,e,f){var g='<div id="'+d.wId+"-"+a+'" class="photo">'+'<div class="image-preview"><img src="'+b+'"/></div><div class="caption">';return d.hasName&&(g+="<h5>"+c+"</h5>"),d.hasDesc&&(g+="<p>"+e+"</p>"),g+='</div><input type="hidden" name="order['+a+']" value="'+f+'"/><div class="actions">'+(d.hasName||d.hasDesc?'<span data-photo-id="'+a+'" class="editPhoto btn btn-primary"><i class="icon-edit icon-white"></i></span> ':"")+'<span data-photo-id="'+a+'" class="deletePhoto btn btn-danger"><i class="icon-remove icon-white"></i></span>'+'</div><input type="checkbox" class="photo-select"/></div>',g}function l(b){b.preventDefault();var c=a(this).data("photo-id");return a.ajax({type:"POST",url:d.deleteUrl,data:"id="+c,success:function(b){b=="OK"?a("#"+d.wId+"-"+c).remove():alert(b)}}),!1}function m(b){b.preventDefault();var c=a(this).data("photo-id"),d=a(this).parents(".photo"),e=a("img",d[0]).attr("src"),f=a(".caption h5",d[0]).text(),g=a(".caption p",d[0]).text();return i.html(j(c,e,f,g)),h.modal("show"),!1}function n(){var b=a(".photo.selected",f).length;a(".select_all",e).prop("checked",a(".photo",f).length==b),b==0?a(".edit_selected, .remove_selected",e).addClass("disabled"):a(".edit_selected, .remove_selected",e).removeClass("disabled")}function o(){var b=a(this);b.is(":checked")?b.parent().addClass("selected"):b.parent().removeClass("selected"),n()}function p(b){a(".deletePhoto",b).click(l),a(".editPhoto",b).click(m),a(".photo-select",b).change(o)}this.defaults={nameLabel:"Name",descriptionLabel:"Description",hasName:!0,hasDesc:!0,uploadUrl:"",deleteUrl:"",updateUrl:"",arrangeUrl:""};var d=a.extend({},this.defaults,c),e=a(b);d.wId=e.attr("id");var f=a(".sorter",e),g=a(".images",f),h=a(".editor-modal",e),i=a(".form",h);p(a(".photo",e)),a(".images",f).sortable().disableSelection().bind("sortstop",function(){a.post(d.arrangeUrl,a("input",f).serialize()+"&ajax=true",function(){},"json")}),typeof window.FormData=="function"?a(".afile",e).attr("multiple","true").on("change",function(b){b.preventDefault();var c=this.files.length,e=0;i.html("");for(var f=0;f<c;f++){var l=new FormData;l.append(this.name,this.files[f]);var m=new XMLHttpRequest;m.open("POST",d.uploadUrl,!0),m.onload=function(){e++;if(this.status==200){var b=JSON.parse(this.response),f=a(k(b.id,b.preview,b.name,b.description,b.rank));p(f),g.append(f),(d.hasName||d.hasDesc)&&i.append(a(j(b.id,b.preview,b.name,b.description)))}e===c&&(d.hasName||d.hasDesc)&&h.modal("show")},m.send(l)}}):a(".afile",e).on("change",function(b){b.preventDefault(),i.html(""),a.ajax(d.uploadUrl,{files:a(this),iframe:!0,dataType:"json"}).done(function(b){var c=a(k(b.id,b.preview,b.name,b.description,b.rank));p(c),g.append(c),(d.hasName||d.hasDesc)&&i.append(a(j(b.id,b.preview,b.name,b.description))),(d.hasName||d.hasDesc)&&h.modal("show")})}),a(".save-changes",h).click(function(b){b.preventDefault(),a.post(d.updateUrl,a("input, textarea",i).serialize()+"&ajax=true",function(b){var c=b.length;for(var g=0;g<c;g++){var i=b[g],j=a("#"+d.wId+"-"+i.id);a("img",j).attr("src",i.src),d.hasName&&a(".caption h5",j).text(i.name),d.hasDesc&&a(".caption p",j).text(i.description)}h.modal("hide"),a(".photo.selected",f).each(function(){a(".photo-select",this).prop("checked",!1)}).removeClass("selected"),a(".select_all",e).prop("checked",!1),n()},"json")}),a(".edit_selected",e).click(function(b){b.preventDefault();var c=0,e=i.html("");return a(".photo.selected",f).each(function(){c++;var b=a(this),f=b.attr("id").substr((d.wId+"-").length),g=a("img",b[0]).attr("src"),h=a(".caption h5",b[0]).text(),i=a(".caption p",b[0]).text();e.append(j(f,g,h,i))}),c>0&&h.modal("show"),!1}),a(".remove_selected",e).click(function(b){b.preventDefault(),a(".photo.selected",f).each(function(){var b=a(this).attr("id").substr((d.wId+"-").length);a.ajax({type:"POST",url:d.deleteUrl,data:"id="+b,success:function(c){c=="OK"?a("#"+d.wId+"-"+b).remove():alert(c)}})})}),a(".select_all",e).change(function(){a(this).prop("checked")?a(".photo",f).each(function(){a(".photo-select",this).prop("checked",!0)}).addClass("selected"):a(".photo.selected",f).each(function(){a(".photo-select",this).prop("checked",!1)}).removeClass("selected"),n()})}a.fn.galleryManager=function(a){this.length&&this.each(function(){b(this,a)})}})(jQuery);

File views/galleryManager.php

             <a href="#" class="btn" data-dismiss="modal"><?php echo Yii::t('galleryManager.main', 'Close')?></a>
         </div>
     </div>
-</div>
-
-<?php
-$cs = Yii::app()->getClientScript();
-$cs->registerCoreScript('jquery');
-$cs->registerCoreScript('jquery.ui');
-
-$url = Yii::app()->createUrl($this->controllerRoute . '/delete', array('id' => ''));
-
-$css = <<<EOD
-    /* Photo Gallery */
-    .GalleryEditor {
-        border: 1px solid #DDD;
-        -webkit-border-radius: 4px;
-        -moz-border-radius: 4px;
-        border-radius: 4px;
-        -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-        -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-    }
-
-    .GalleryEditor div.gform {
-        padding-top: 4px;
-        clear: left;
-    }
-    .GalleryEditor form{
-        margin: 0;
-    }
-
-    .GalleryEditor .photo {
-        position: relative;
-        float: left;
-        background-color: #fff;
-        margin: 4px;
-        height: 178px;
-        width:140px;
-
-        display: block;
-        padding: 4px;
-        line-height: 1;
-        border: 1px solid #DDD;
-        -webkit-border-radius: 4px;
-        -moz-border-radius: 4px;
-        border-radius: 4px;
-        -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-        -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-    }
-
-    .GalleryEditor .photo img {
-        width: 140px;
-        height: auto;
-    }
-
-    .GalleryEditor .photo a {
-        padding-left: 8px;
-    }
-
-    .GalleryEditor .photo .actions {
-        float: right;
-
-        position: absolute;
-        bottom: 4px;
-        right: 4px;
-    }
-
-
-    .GalleryEditor hr{
-        margin: 0 4px;
-    }
-
-    .GalleryEditor .fileinput-button {
-        position: relative;
-        overflow: hidden;
-        margin-left: 8px;
-        margin-top: 4px;
-        margin-bottom: 4px;
-    }
-    .GalleryEditor .fileinput-button input {
-        position: absolute;
-        top: 0;
-        right: 0;
-        margin: 0;
-        border: solid transparent;
-        border-width: 0 0 100px 200px;
-        opacity: 0;
-        filter: alpha(opacity=0);
-        -moz-transform: translate(-300px, 0) scale(4);
-        direction: ltr;
-        cursor: pointer;
-    }
-
-    /* modal styles*/
-    .GalleryEditor .preview {
-        overflow: hidden;
-        width: 200px;
-        height: 156px;
-        margin-right: 10px;
-        overflow: hidden;
-        float: left;
-    }
-
-    .GalleryEditor .preview img {
-        width: 200px;
-    }
-
-    .GalleryEditor .photo-editor {
-        min-height:156px;
-        margin-bottom: 4px;
-        padding: 4px;
-        border: 1px solid #DDD;
-        -webkit-border-radius: 4px;
-        -moz-border-radius: 4px;
-        border-radius: 4px;
-        -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-        -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-    }
-
-    .photo-editor form {
-        margin-bottom: 0;
-    }
-
-    .GalleryEditor .caption p{
-        height: 40px;
-        overflow: hidden;
-    }
-
-    /* fixed thumbnail sizes */
-    .GalleryEditor.no-desc .photo{
-        height: 138px;
-    }
-    .GalleryEditor.no-name .photo{
-        height: 160px;
-    }
-    .GalleryEditor.no-name-no-desc .photo{
-        height: 120px;
-    }
-    .GalleryEditor .image-preview{
-        height: 88px;
-        overflow: hidden;
-    }
-    /* item selection */
-    .GalleryEditor .photo-select{
-        position: absolute;
-        bottom: 8px;
-        left: 8px;
-    }
-    .GalleryEditor .photo.selected{
-        background-color: #cef;
-        border-color: blue;
-    }
-EOD;
-
-$cs->registerCss($this->id . 'css', $css);
-?>
-
-<script type="text/javascript">
-$(function () {
-    // variables from php
-    var hasName = <?php echo $this->gallery->name ? 'true' : 'false' ?>;
-    var hasDesc = <?php echo $this->gallery->description ? 'true' : 'false' ?>;
-
-    var wId = '<?php echo $this->id?>';
-    var ajaxUploadUrl = <?php echo CJavaScript::encode(Yii::app()->createUrl($this->controllerRoute . '/ajaxUpload', array('gallery_id' => $this->gallery->id)))?>;
-    var deleteUrl = <?php echo CJavaScript::encode(Yii::app()->createUrl($this->controllerRoute . '/delete'))?>;
-    var editorActionUrl = <?php echo CJavaScript::encode(Yii::app()->createUrl($this->controllerRoute . '/changeData'))?>;
-    var sorterActionUrl = <?php echo CJavaScript::encode(Yii::app()->createUrl($this->controllerRoute . '/order'));?>;
-
-
-    var $gallery = $('#' + wId);
-    var $sorter = $('.sorter', $gallery);
-    var $images = $('.images', $sorter);
-    var $editorModal = $('.editor-modal');
-    var $editorForm = $('.form', $editorModal);
-
-
-    function photoEditorTemplate(id, src, name, description) {
-        return '<div class="photo-editor">' +
-            '<div class="preview"><img src="' + src + '" alt=""/></div>' +
-            '<div>' +
-            (hasName
-                ? '<label for="photo_name_' + id + '"><?php echo Yii::t('galleryManager.main', 'Name');?>:</label>' +
-                '<input type="text" name="photo[' + id + '][name]" class="input-xlarge" value="' + name + '" id="photo_name_' + id + '"/>'
-                : '') +
-            (hasDesc
-                ? '<label for="photo_description_' + id + '"><?php echo Yii::t('galleryManager.main', 'Description');?>:</label>' +
-                '<textarea name="photo[' + id + '][description]" rows="3" cols="40" class="input-xlarge" id="photo_description_' + id + '">' + description + '</textarea>'
-                : '') +
-            '</div>' +
-            '</div>';
-    }
-
-    function photoTemplate(id, src, name, description, rank) {
-        var res = '<div id="' + wId + '-' + id + '" class="photo">' +
-            '<div class="image-preview"><img src="' + src + '"/></div><div class="caption">';
-        if (hasName)res += '<h5>' + name + '</h5>';
-        if (hasDesc)res += '<p>' + description + '</p>';
-        res += '</div><input type="hidden" name="order[' + id + ']" value="' + rank + '"/><div class="actions">' +
-
-            ((hasName || hasDesc)
-                ? '<span data-photo-id="' + id + '" class="editPhoto btn btn-primary"><i class="icon-edit icon-white"></i></span> '
-                : '') +
-            '<span data-photo-id="' + id + '" class="deletePhoto btn btn-danger"><i class="icon-remove icon-white"></i></span>' +
-            '</div><input type="checkbox" class="photo-select"/></div>';
-        return res;
-    }
-
-    function deleteClick(e) {
-        e.preventDefault();
-        var id = $(this).data('photo-id');
-        //if (!confirm(deleteConfirmation)) return false;
-        $.ajax({
-            type:'POST',
-            url:deleteUrl,
-            data:'id=' + id,
-            success:function (t) {
-                if (t == 'OK') $('#' + wId + '-' + id).remove();
-                else alert(t);
-            }});
-        return false;
-    }
-
-    function editClick(e) {
-        e.preventDefault();
-        var id = $(this).data('photo-id');
-        var photo = $(this).parents('.photo');
-        var src = $('img', photo[0]).attr('src');
-        var name = $('.caption h5', photo[0]).text();
-        var description = $('.caption p', photo[0]).text();
-        $editorForm.html(photoEditorTemplate(id, src, name, description));
-        $editorModal.modal('show');
-        return false;
-    }
-
-    function updateButtons() {
-        var selectedCount = $('.photo.selected', $sorter).length;
-        $('.select_all', $gallery).prop('checked', $('.photo', $sorter).length == selectedCount);
-        if (selectedCount == 0) {
-            $('.edit_selected, .remove_selected', $gallery).addClass('disabled');
-        } else {
-            $('.edit_selected, .remove_selected', $gallery).removeClass('disabled');
-        }
-    }
-
-    function selectChanged() {
-        var $this = $(this);
-        if ($this.is(':checked'))
-            $this.parent().addClass('selected');
-        else
-            $this.parent().removeClass('selected');
-        updateButtons();
-    }
-
-    function bindPhotoEvents(newOne) {
-        $('.deletePhoto', newOne).click(deleteClick);
-        $('.editPhoto', newOne).click(editClick);
-        $('.photo-select', newOne).change(selectChanged);
-    }
-
-    bindPhotoEvents($('.photo'));
-
-    $('.images', $sorter).sortable().disableSelection().bind("sortstop", function (event, ui) {
-        $.post(sorterActionUrl, $('input', $sorter).serialize() + '&ajax=true', function (data, textStatus, jqXHR) {
-            // order saved!
-        }, 'json');
-    });
-
-
-    if (typeof window.FormData == 'function') {  // if XHR2 available
-        $('.afile', $gallery).attr('multiple', 'true').on('change', function (e) {
-            e.preventDefault();
-            var filesCount = this.files.length;
-            var uploadedCount = 0;
-            $editorForm.html('');
-
-            for (var i = 0; i < filesCount; i++) {
-                var fd = new FormData();
-                fd.append(this.name, this.files[i]);
-                var xhr = new XMLHttpRequest();
-                xhr.open('POST', ajaxUploadUrl, true);
-                xhr.onload = function () {
-                    uploadedCount++;
-                    if (this.status == 200) {
-                        var resp = JSON.parse(this.response);
-                        var newOne = $(photoTemplate(resp.id, resp.preview, resp.name, resp.description, resp.rank));
-
-                        bindPhotoEvents(newOne);
-
-                        $images.append(newOne);
-                        if (hasName || hasDesc)
-                            $editorForm.append($(photoEditorTemplate(resp.id, resp.preview, resp.name, resp.description)));
-                    }
-                    if (uploadedCount === filesCount && (hasName || hasDesc)) $editorModal.modal('show');
-                };
-                xhr.send(fd);
-            }
-        });
-    } else {
-        $('.afile', $gallery).on('change', function (e) {
-            //this.form.submit(); // todo: iframe xhr
-            e.preventDefault();
-            $editorForm.html('');
-
-            $.ajax(
-                ajaxUploadUrl, {
-                    files:$(this),
-                    iframe:true,
-                    dataType:"json"
-                }).done(function (resp) {
-                    var newOne = $(photoTemplate(resp.id, resp.preview, resp.name, resp.description, resp.rank));
-                    bindPhotoEvents(newOne);
-                    $images.append(newOne);
-                    if (hasName || hasDesc)
-                        $editorForm.append($(photoEditorTemplate(resp.id, resp.preview, resp.name, resp.description)));
-
-                    if (hasName || hasDesc) $editorModal.modal('show');
-                });
-
-
-        });
-    }
-
-    $('.save-changes', $editorModal).click(function (e) {
-        e.preventDefault();
-        $.post(editorActionUrl, $('input,textarea', $editorForm).serialize() + '&ajax=true', function (data, textStatus, jqXHR) {
-
-            var count = data.length;
-            for (var key = 0; key < count; key++) {
-                var p = data[key];
-                var photo = $('#' + wId + '-' + p.id);
-                $('img', photo).attr('src', p.src);
-                $('.caption h5', photo).text(p.name);
-                $('.caption p', photo).text(p.description);
-            }
-            $editorModal.modal('hide');
-            //deselect all items after editing
-            $('.photo.selected', $sorter).each(function () {
-                $('.photo-select', this).prop('checked', false)
-            }).removeClass('selected');
-            $('.select_all', $gallery).prop('checked', false);
-            updateButtons();
-        }, 'json');
-
-    });
-
-    $('.edit_selected').click(function (e) {
-        e.preventDefault();
-        var cc = 0;
-        var form = $editorForm.html('');
-        $('.photo.selected', $sorter).each(function () {
-            cc++;
-            var photo = $(this),
-                id = photo.attr('id').substr((wId + '-').length),
-                src = $('img', photo[0]).attr('src'),
-                name = $('.caption h5', photo[0]).text(),
-                description = $('.caption p', photo[0]).text();
-            form.append(photoEditorTemplate(id, src, name, description));
-        });
-        if (cc > 0)$editorModal.modal('show');
-        return false;
-    });
-
-    $('.remove_selected', $gallery).click(function (e) {
-        e.preventDefault();
-        $('.photo.selected', $sorter).each(function () {
-            var id = $(this).attr('id').substr((wId + '-').length);
-            $.ajax({
-                type:'POST',
-                url:deleteUrl,
-                data:'id=' + id,
-                success:function (t) {
-                    if (t == 'OK') $('#' + wId + '-' + id).remove();
-                    else alert(t);
-                }});
-        });
-    });
-
-    $('.select_all', $gallery).change(function (e) {
-        if ($(this).prop('checked')) {
-            $('.photo', $sorter).each(function () {
-                $('.photo-select', this).prop('checked', true)
-            }).addClass('selected');
-        } else {
-            $('.photo.selected', $sorter).each(function () {
-                $('.photo-select', this).prop('checked', false)
-            }).removeClass('selected');
-        }
-        updateButtons();
-    });
-
-})
-</script>
+</div>