diff --git a/README.md b/README.md index 0059d7ec..f44d73c2 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ * ImageMagick or GraphicsMagick (for MiniMagick); * [Bootstrap 3](http://getbootstrap.com/) fully installed in your app. +* jQuery ## Installation diff --git a/app/assets/javascripts/bootsy/area.js b/app/assets/javascripts/bootsy/area.js index 484bb756..a12f0767 100644 --- a/app/assets/javascripts/bootsy/area.js +++ b/app/assets/javascripts/bootsy/area.js @@ -1,90 +1,96 @@ -/* global Bootsy */ - -window.Bootsy = window.Bootsy || {}; - -Bootsy.Area = function($el) { - var self = this; - - this.$el = $el; - this.unsavedChanges = false; - this.locale = $el.data('bootsy-locale') || $('html').attr('lang'); - if (!$.fn.wysihtml5.locale.hasOwnProperty(this.locale)) this.locale = 'en'; - - this.options = { - locale: this.locale, - alertUnsavedChanges: $el.data('bootsy-alert-unsaved'), - uploader: $el.data('bootsy-uploader'), - color: $el.data('bootsy-color'), - emphasis: $el.data('bootsy-emphasis'), - 'font-styles': $el.data('bootsy-font-styles'), - html: $el.data('bootsy-html'), - image: $el.data('bootsy-image'), - link: $el.data('bootsy-link'), - lists: $el.data('bootsy-lists'), - events: { - change: function() { - self.unsavedChanges = true; - $el.trigger('change'); +(function($) { + /* global Bootsy */ + + window.Bootsy = window.Bootsy || {}; + + Bootsy.Area = function($el) { + var self = this; + + this.$el = $el; + this.unsavedChanges = false; + this.locale = $el.data("bootsy-locale") || $("html").attr("lang"); + if (!$.fn.wysihtml5.locale.hasOwnProperty(this.locale)) this.locale = "en"; + + this.options = { + locale: this.locale, + alertUnsavedChanges: $el.data("bootsy-alert-unsaved"), + uploader: $el.data("bootsy-uploader"), + color: $el.data("bootsy-color"), + emphasis: $el.data("bootsy-emphasis"), + "font-styles": $el.data("bootsy-font-styles"), + html: $el.data("bootsy-html"), + image: $el.data("bootsy-image"), + link: $el.data("bootsy-link"), + lists: $el.data("bootsy-lists"), + events: { + change: function() { + self.unsavedChanges = true; + $el.trigger("change"); + } } - } + }; }; -}; - -// Alert for unsaved changes -Bootsy.Area.prototype.unsavedChangesAlert = function () { - if (this.unsavedChanges) { - return $.fn.wysihtml5.locale[this.locale].bootsy.alertUnsaved; - } -}; - -// Clear everything -Bootsy.Area.prototype.clear = function () { - this.editor.clear(); - this.setImageGalleryId(''); - this.modal.$el.data('gallery-loaded', false); -}; - -Bootsy.Area.prototype.setImageGalleryId = function(id) { - this.$el.data('gallery-id', id); - this.$el.siblings('.bootsy_image_gallery_id').val(id); -}; - -// Init components -Bootsy.Area.prototype.init = function() { - if (!this.$el.data('bootsy-initialized')) { - if ((this.options.image === true) && (this.options.uploader === true)) { - this.modal = new Bootsy.Modal(this); - this.options.image = false; - this.options.customCommand = true; - this.options.customCommandCallback = this.modal.show.bind(this.modal); - this.options.customTemplates = { customCommand: Bootsy.imageTemplate }; + + // Alert for unsaved changes + Bootsy.Area.prototype.unsavedChangesAlert = function() { + if (this.unsavedChanges) { + return $.fn.wysihtml5.locale[this.locale].bootsy.alertUnsaved; } + }; - this.editor = this.$el.wysihtml5($.extend(true, {}, Bootsy.options, this.options)).data('wysihtml5').editor; + // Clear everything + Bootsy.Area.prototype.clear = function() { + this.editor.clear(); + this.setImageGalleryId(""); + this.modal.$el.data("gallery-loaded", false); + }; - // Mechanism for unsaved changes alert - if (this.options.alertUnsavedChanges !== false) { - window.onbeforeunload = this.unsavedChangesAlert.bind(this); - } + Bootsy.Area.prototype.setImageGalleryId = function(id) { + this.$el.data("gallery-id", id); + this.$el.siblings(".bootsy_image_gallery_id").val(id); + }; - this.$el.closest('form').submit(function() { - this.unsavedChanges = false; + // Init components + Bootsy.Area.prototype.init = function() { + if (!this.$el.data("bootsy-initialized")) { + if (this.options.image === true && this.options.uploader === true) { + this.modal = new Bootsy.Modal(this); + this.options.image = false; + this.options.customCommand = true; + this.options.customCommandCallback = this.modal.show.bind(this.modal); + this.options.customTemplates = { customCommand: Bootsy.imageTemplate }; + } - return true; - }.bind(this)); + this.editor = this.$el + .wysihtml5($.extend(true, {}, Bootsy.options, this.options)) + .data("wysihtml5").editor; - this.$el.data('bootsy-initialized', true); - } -}; + // Mechanism for unsaved changes alert + if (this.options.alertUnsavedChanges !== false) { + window.onbeforeunload = this.unsavedChangesAlert.bind(this); + } -// Insert image in the text -Bootsy.Area.prototype.insertImage = function(image) { - this.editor.currentView.element.focus(); + this.$el.closest("form").submit( + function() { + this.unsavedChanges = false; - if (this.caretBookmark) { - this.editor.composer.selection.setBookmark(this.caretBookmark); - this.caretBookmark = null; - } + return true; + }.bind(this) + ); - this.editor.composer.commands.exec('insertImage', image); -}; + this.$el.data("bootsy-initialized", true); + } + }; + + // Insert image in the text + Bootsy.Area.prototype.insertImage = function(image) { + this.editor.currentView.element.focus(); + + if (this.caretBookmark) { + this.editor.composer.selection.setBookmark(this.caretBookmark); + this.caretBookmark = null; + } + + this.editor.composer.commands.exec("insertImage", image); + }; +})(jQuery); diff --git a/app/assets/javascripts/bootsy/editor_options.js b/app/assets/javascripts/bootsy/editor_options.js index 908a3fa6..0b5687f6 100644 --- a/app/assets/javascripts/bootsy/editor_options.js +++ b/app/assets/javascripts/bootsy/editor_options.js @@ -1,47 +1,49 @@ -window.Bootsy = window.Bootsy || {}; +(function($) { + window.Bootsy = window.Bootsy || {}; -var pageStylesheets = []; -$('link[rel="stylesheet"]').each(function () { - pageStylesheets.push($(this).attr('href')); -}); + var pageStylesheets = []; + $('link[rel="stylesheet"]').each(function() { + pageStylesheets.push($(this).attr("href")); + }); -window.Bootsy.options = {}; + window.Bootsy.options = {}; -$.extend(true, window.Bootsy.options, $.fn.wysihtml5.defaultOptions, { - parserRules: { - classes: { - "wysiwyg-float-left": 1, - "wysiwyg-float-right": 1, - "wysiwyg-float-inline": 1 - }, - tags: { - "cite": { - "check_attributes": { - "title": "alt" - } + $.extend(true, window.Bootsy.options, $.fn.wysihtml5.defaultOptions, { + parserRules: { + classes: { + "wysiwyg-float-left": 1, + "wysiwyg-float-right": 1, + "wysiwyg-float-inline": 1 }, - "img": { - "check_attributes": { - "src": "src" + tags: { + cite: { + check_attributes: { + title: "alt" + } }, - "add_class": { - "align": "align_img" - } - }, - // this allows youtube embed codes - "iframe": { - set_attributes: { - "frameborder": "0", - "allowfullscreen": "1" + img: { + check_attributes: { + src: "src" + }, + add_class: { + align: "align_img" + } }, - check_attributes: { - "width": "numbers", - "height": "numbers", - "src": "href" + // this allows youtube embed codes + iframe: { + set_attributes: { + frameborder: "0", + allowfullscreen: "1" + }, + check_attributes: { + width: "numbers", + height: "numbers", + src: "href" + } } } - } - }, - color: true, - stylesheets: pageStylesheets -}); + }, + color: true, + stylesheets: pageStylesheets + }); +})(jQuery); diff --git a/app/assets/javascripts/bootsy/init.js b/app/assets/javascripts/bootsy/init.js index 192ba9e4..cd179269 100644 --- a/app/assets/javascripts/bootsy/init.js +++ b/app/assets/javascripts/bootsy/init.js @@ -1,36 +1,38 @@ -/* global Bootsy */ -window.Bootsy = window.Bootsy || {}; +(function($) { + /* global Bootsy */ + window.Bootsy = window.Bootsy || {}; -// Public: Intialize Bootsy editors in all visible `textarea` -// elements that has the `bootsy_text_area` class. -Bootsy.init = function() { - if (!Bootsy.areas) { - Bootsy.areas = {}; - } + // Public: Intialize Bootsy editors in all visible `textarea` + // elements that has the `bootsy_text_area` class. + Bootsy.init = function() { + if (!Bootsy.areas) { + Bootsy.areas = {}; + } - $('textarea.bootsy_text_area').each(function(index) { - if (!$(this).data('bootsy-initialized')) { - var area = new Bootsy.Area($(this)); - var areaIdx = $(this).attr('id') || index; + $("textarea.bootsy_text_area").each(function(index) { + if (!$(this).data("bootsy-initialized")) { + var area = new Bootsy.Area($(this)); + var areaIdx = $(this).attr("id") || index; - /* There's always people who let elements share ids */ - if(Bootsy.areas[areaIdx] !== undefined) { - areaIdx = $(this).attr('id') + index; - } + /* There's always people who let elements share ids */ + if (Bootsy.areas[areaIdx] !== undefined) { + areaIdx = $(this).attr("id") + index; + } - area.init(); + area.init(); - Bootsy.areas[areaIdx] = area; - } - }); -}; + Bootsy.areas[areaIdx] = area; + } + }); + }; -/* Initialize Bootsy on document load */ -$(function() { - $(window).on('load', function() { - Bootsy.init(); + /* Initialize Bootsy on document load */ + $(function() { + $(window).on("load", function() { + Bootsy.init(); - /* Reload Bootsy on page load when using Turbolinks. */ - document.addEventListener('turbolinks:load', Bootsy.init); + /* Reload Bootsy on page load when using Turbolinks. */ + document.addEventListener("turbolinks:load", Bootsy.init); + }); }); -}); +})(jQuery); diff --git a/app/assets/javascripts/bootsy/locales/en.js b/app/assets/javascripts/bootsy/locales/en.js index efb7e37f..9ce134dc 100644 --- a/app/assets/javascripts/bootsy/locales/en.js +++ b/app/assets/javascripts/bootsy/locales/en.js @@ -1,54 +1,54 @@ /** * English translations for bootstrap-wysihtml5 and Bootsy */ -(function($){ - $.fn.wysihtml5.locale['en'] = { +(function($) { + $.fn.wysihtml5.locale["en"] = { font_styles: { - normal: 'Normal text', - h1: 'Heading 1', - h2: 'Heading 2', - h3: 'Heading 3' + normal: "Normal text", + h1: "Heading 1", + h2: "Heading 2", + h3: "Heading 3" }, emphasis: { - bold: 'Bold', - italic: 'Italic', - underline: 'Underline', - small: 'Small' + bold: "Bold", + italic: "Italic", + underline: "Underline", + small: "Small" }, lists: { - unordered: 'Unordered list', - ordered: 'Ordered list', - outdent: 'Outdent', - indent: 'Indent' + unordered: "Unordered list", + ordered: "Ordered list", + outdent: "Outdent", + indent: "Indent" }, link: { - insert: 'Insert link', - cancel: 'Cancel', - target: 'Open link in new window' + insert: "Insert link", + cancel: "Cancel", + target: "Open link in new window" }, image: { - insert: 'Insert image', - cancel: 'Cancel' + insert: "Insert image", + cancel: "Cancel" }, html: { - edit: 'Edit HTML' + edit: "Edit HTML" }, colours: { - black: 'Black', - silver: 'Silver', - gray: 'Grey', - maroon: 'Maroon', - red: 'Red', - purple: 'Purple', - green: 'Green', - olive: 'Olive', - navy: 'Navy', - blue: 'Blue', - orange: 'Orange' + black: "Black", + silver: "Silver", + gray: "Grey", + maroon: "Maroon", + red: "Red", + purple: "Purple", + green: "Green", + olive: "Olive", + navy: "Navy", + blue: "Blue", + orange: "Orange" }, bootsy: { - alertUnsaved: 'You have unsaved changes.', - error: 'Something went wrong. Please try again later.' + alertUnsaved: "You have unsaved changes.", + error: "Something went wrong. Please try again later." } }; -}(jQuery)); +})(jQuery); diff --git a/app/assets/javascripts/bootsy/locales/pt-BR.js b/app/assets/javascripts/bootsy/locales/pt-BR.js index 0ced857c..db45e689 100644 --- a/app/assets/javascripts/bootsy/locales/pt-BR.js +++ b/app/assets/javascripts/bootsy/locales/pt-BR.js @@ -1,54 +1,54 @@ /** * Brazilian portuguese translation for bootstrap-wysihtml5 and Bootsy */ -(function($){ - $.fn.wysihtml5.locale['pt-BR'] = { +(function($) { + $.fn.wysihtml5.locale["pt-BR"] = { font_styles: { - normal: 'Texto normal', - h1: 'Título 1', - h2: 'Título 2', - h3: 'Título 3' + normal: "Texto normal", + h1: "Título 1", + h2: "Título 2", + h3: "Título 3" }, emphasis: { - bold: 'Negrito', - italic: 'Itálico', - underline: 'Sublinhado', - small: 'Pequeno' + bold: "Negrito", + italic: "Itálico", + underline: "Sublinhado", + small: "Pequeno" }, lists: { - unordered: 'Lista', - ordered: 'Lista numerada', - outdent: 'Remover indentação', - indent: 'Indentar' + unordered: "Lista", + ordered: "Lista numerada", + outdent: "Remover indentação", + indent: "Indentar" }, link: { - insert: 'Inserir link', - cancel: 'Cancelar', - target: 'Abrir link em um nova janela' + insert: "Inserir link", + cancel: "Cancelar", + target: "Abrir link em um nova janela" }, image: { - insert: 'Inserir imagem', - cancel: 'Cancelar' + insert: "Inserir imagem", + cancel: "Cancelar" }, html: { - edit: 'Editar HTML' + edit: "Editar HTML" }, colours: { - black: 'Preto', - silver: 'Prata', - gray: 'Cinza', - maroon: 'Marrom', - red: 'Vermelho', - purple: 'Roxo', - green: 'Verde', - olive: 'Oliva', - navy: 'Marinho', - blue: 'Azul', - orange: 'Laranja' + black: "Preto", + silver: "Prata", + gray: "Cinza", + maroon: "Marrom", + red: "Vermelho", + purple: "Roxo", + green: "Verde", + olive: "Oliva", + navy: "Marinho", + blue: "Azul", + orange: "Laranja" }, bootsy: { - alertUnsaved: 'As suas modificações ainda não foram gravadas.', - error: 'Algo deu errado. Por favor, tente novamente.' + alertUnsaved: "As suas modificações ainda não foram gravadas.", + error: "Algo deu errado. Por favor, tente novamente." } }; -}(jQuery)); +})(jQuery); diff --git a/app/assets/javascripts/bootsy/modal.js b/app/assets/javascripts/bootsy/modal.js index 1db6b452..6bee9b9b 100644 --- a/app/assets/javascripts/bootsy/modal.js +++ b/app/assets/javascripts/bootsy/modal.js @@ -1,225 +1,259 @@ -/* Bootsy modal */ +(function($) { + /* Bootsy modal */ -window.Bootsy = window.Bootsy || {}; + window.Bootsy = window.Bootsy || {}; -Bootsy.Modal = function(area) { - var self = this; + Bootsy.Modal = function(area) { + var self = this; - this.$el = area.$el.siblings('.bootsy-modal'); - this.area = area; + this.$el = area.$el.siblings(".bootsy-modal"); + this.area = area; - // In order to avoid form nesting - this.$el.parents('form').after(this.$el); + // In order to avoid form nesting + this.$el.parents("form").after(this.$el); - this.$el.on('click', '.bootsy-image .insert', function(event) { - var img, imageObject; - var imagePrefix = '/' + $(this).attr('data-image-size') + '_'; + this.$el.on("click", ".bootsy-image .insert", function(event) { + var img, imageObject; + var imagePrefix = "/" + $(this).attr("data-image-size") + "_"; - event.preventDefault(); + event.preventDefault(); - if ($(this).data('image-size') === 'original') { - imagePrefix = '/'; - } - - img = $(this).parents('.bootsy-image').find('img'); - - imageObject = { - src: img.attr('src').replace('/thumb_', imagePrefix), - alt: img.attr('alt').replace('Thumb_', '') - }; - - imageObject.align = $(this).data('position'); - - self.$el.modal('hide'); - - insert = self.area.insertImage.bind(self.area); - insert(imageObject); - }); - - this.$el.on('ajax:before', '.destroy-btn', this.showGalleryLoadingAnimation.bind(this)); - - this.$el.on('ajax:success', '.destroy-btn', function(_e, data) { - this.deleteImage(data.id); - }.bind(this)); - - this.$el.on('click', 'a[href="#refresh-gallery"]', this.requestImageGallery.bind(this)); - - this.$el.on('submit', '.bootsy-upload-form', function(event, xhr, settings) { - var fileSelect = event.target.querySelector('input[type="file"]'); - var formData = new FormData(); - var file = fileSelect.files[0]; - var fileURLInputName = 'image[remote_image_file_url]'; - var fileURLInput = event.target.querySelector( - 'input[name="' + fileURLInputName + '"]'); - var fileURL; - - event.preventDefault(); - - formData.append('authenticity_token', - event.target.querySelector('input[name="authenticity_token"]').value); - - if (file) { - formData.append('image[image_file]', file, file.name); - } + if ($(this).data("image-size") === "original") { + imagePrefix = "/"; + } - if (fileURLInput) { - fileURL = fileURLInput.value; + img = $(this).parents(".bootsy-image").find("img"); + + imageObject = { + src: img.attr("src").replace("/thumb_", imagePrefix), + alt: img.attr("alt").replace("Thumb_", "") + }; + + imageObject.align = $(this).data("position"); + + self.$el.modal("hide"); + + insert = self.area.insertImage.bind(self.area); + insert(imageObject); + }); + + this.$el.on( + "ajax:before", + ".destroy-btn", + this.showGalleryLoadingAnimation.bind(this) + ); + + this.$el.on( + "ajax:success", + ".destroy-btn", + function(_e, data) { + this.deleteImage(data.id); + }.bind(this) + ); + + this.$el.on( + "click", + 'a[href="#refresh-gallery"]', + this.requestImageGallery.bind(this) + ); + + this.$el.on( + "submit", + ".bootsy-upload-form", + function(event, xhr, settings) { + var fileSelect = event.target.querySelector('input[type="file"]'); + var formData = new FormData(); + var file = fileSelect.files[0]; + var fileURLInputName = "image[remote_image_file_url]"; + var fileURLInput = event.target.querySelector( + 'input[name="' + fileURLInputName + '"]' + ); + var fileURL; + + event.preventDefault(); + + formData.append( + "authenticity_token", + event.target.querySelector('input[name="authenticity_token"]').value + ); + + if (file) { + formData.append("image[image_file]", file, file.name); + } + + if (fileURLInput) { + fileURL = fileURLInput.value; + } else { + fileURL = ""; + } + + formData.append(fileURLInputName, fileURL); + + var xhr = new XMLHttpRequest(); + xhr.open("POST", event.target.action, true); + xhr.onload = function() { + var data = JSON.parse(xhr.response); + if (xhr.status === 200) { + this.area.setImageGalleryId(data.gallery_id); + this.addImage(data.image); + this.setUploadForm(data.form); + } else { + this.imageUploadFailed(xhr, data); + } + }.bind(this); + xhr.send(formData); + }.bind(this) + ); + + this.$el.modal({ show: false }); + + this.$el.on( + "shown.bs.modal", + function() { + if (this.$el.data("gallery-loaded") !== true) { + this.requestImageGallery(); + } + }.bind(this) + ); + + this.hideRefreshButton(); + this.hideEmptyAlert(); + }; + + // Show modal + Bootsy.Modal.prototype.show = function() { + this.$el.modal("show"); + }; + + // Gallery loading + Bootsy.Modal.prototype.showGalleryLoadingAnimation = function() { + this.$el.find(".bootsy-gallery-loader").fadeIn(200); + }; + + Bootsy.Modal.prototype.hideGalleryLoadingAnimation = function() { + this.$el.find(".bootsy-gallery-loader").fadeOut(200); + }; + + // Upload loading animation + Bootsy.Modal.prototype.showUploadLoadingAnimation = function() { + this.$el.find(".bootsy-upload-loader").fadeIn(200); + }; + + Bootsy.Modal.prototype.hideUploadLoadingAnimation = function() { + this.$el.find(".bootsy-upload-loader").fadeOut(200); + }; + + // Alert for empty gallery + Bootsy.Modal.prototype.showEmptyAlert = function() { + this.$el.find(".bootsy-empty-alert").fadeIn(200); + }; + + Bootsy.Modal.prototype.hideEmptyAlert = function() { + this.$el.find(".bootsy-empty-alert").fadeOut(200); + }; + + // Manual refresh button + Bootsy.Modal.prototype.showRefreshButton = function() { + this.$el.find(".refresh-btn").fadeIn(200); + }; + + Bootsy.Modal.prototype.hideRefreshButton = function() { + this.$el.find(".refresh-btn").fadeOut(200); + }; + + // Set upload form + Bootsy.Modal.prototype.setUploadForm = function(html) { + var uploadInput; + + this.$el.find(".modal-footer").html(html); + this.hideUploadLoadingAnimation(); + this.$el + .find('.bootsy-upload-form input[type="file"]') + .bootstrapFileInput(); + + uploadInput = this.$el.find('.bootsy-upload-form input[type="file"]'); + + uploadInput.change( + function() { + this.showUploadLoadingAnimation(); + uploadInput.closest("form").submit(); + }.bind(this) + ); + }; + + // The image upload failed + Bootsy.Modal.prototype.imageUploadFailed = function(xhr, invalidErrors) { + if (Number(xhr.status) === 422 && invalidErrors.image_file) { + this.hideUploadLoadingAnimation(); + + if (this.validation) this.validation.remove(); + + this.validation = $("

"); + this.validation.text(invalidErrors.image_file[0]); + this.$el.find(".bootsy-upload-form").append(this.validation); } else { - fileURL = ''; + this.hideGalleryLoadingAnimation(); + alert($.fn.wysihtml5.locale[this.area.locale].bootsy.error); } - formData.append(fileURLInputName, fileURL); + this.showRefreshButton(); + }; + + // Add image to gallery + Bootsy.Modal.prototype.addImage = function(html) { + this.hideEmptyAlert(); + + $(html).hide().appendTo(this.$el.find(".bootsy-gallery")).fadeIn(200); + }; + + // Set image gallery + Bootsy.Modal.prototype.requestImageGallery = function() { + this.hideRefreshButton(); + this.showGalleryLoadingAnimation(); + + $.ajax({ + url: "/bootsy/images", + type: "GET", + cache: false, + data: { + image_gallery_id: this.area.$el.data("gallery-id") + }, + dataType: "json", + success: function(data) { + this.hideRefreshButton(); + this.hideGalleryLoadingAnimation(); + this.$el.find(".bootsy-gallery .bootsy-image").remove(); + + $.each( + data.images, + function(index, value) { + this.addImage(value); + }.bind(this) + ); + + if (data.images.length === 0) this.showEmptyAlert(); - var xhr = new XMLHttpRequest(); - xhr.open('POST', event.target.action, true); - xhr.onload = function () { - var data = JSON.parse(xhr.response); - if (xhr.status === 200) { - this.area.setImageGalleryId(data.gallery_id); - this.addImage(data.image); this.setUploadForm(data.form); - } else { - this.imageUploadFailed(xhr, data); - } - }.bind(this); - xhr.send(formData); - }.bind(this)); - this.$el.modal({ show: false }); - - this.$el.on('shown.bs.modal', function() { - if (this.$el.data('gallery-loaded') !== true) { - this.requestImageGallery(); - } - }.bind(this)); - - this.hideRefreshButton(); - this.hideEmptyAlert(); -}; - -// Show modal -Bootsy.Modal.prototype.show = function() { - this.$el.modal('show'); -}; - -// Gallery loading -Bootsy.Modal.prototype.showGalleryLoadingAnimation = function() { - this.$el.find('.bootsy-gallery-loader').fadeIn(200); -}; - -Bootsy.Modal.prototype.hideGalleryLoadingAnimation = function() { - this.$el.find('.bootsy-gallery-loader').fadeOut(200); -}; - -// Upload loading animation -Bootsy.Modal.prototype.showUploadLoadingAnimation = function() { - this.$el.find('.bootsy-upload-loader').fadeIn(200); -}; - -Bootsy.Modal.prototype.hideUploadLoadingAnimation = function() { - this.$el.find('.bootsy-upload-loader').fadeOut(200); -}; - -// Alert for empty gallery -Bootsy.Modal.prototype.showEmptyAlert = function() { - this.$el.find('.bootsy-empty-alert').fadeIn(200); -}; - -Bootsy.Modal.prototype.hideEmptyAlert = function() { - this.$el.find('.bootsy-empty-alert').fadeOut(200); -}; - -// Manual refresh button -Bootsy.Modal.prototype.showRefreshButton = function() { - this.$el.find('.refresh-btn').fadeIn(200); -}; - -Bootsy.Modal.prototype.hideRefreshButton = function() { - this.$el.find('.refresh-btn').fadeOut(200); -}; - -// Set upload form -Bootsy.Modal.prototype.setUploadForm = function(html) { - var uploadInput; - - this.$el.find('.modal-footer').html(html); - this.hideUploadLoadingAnimation(); - this.$el.find('.bootsy-upload-form input[type="file"]').bootstrapFileInput(); - - uploadInput = this.$el.find('.bootsy-upload-form input[type="file"]'); - - uploadInput.change(function() { - this.showUploadLoadingAnimation(); - uploadInput.closest('form').submit(); - }.bind(this)); -}; - -// The image upload failed -Bootsy.Modal.prototype.imageUploadFailed = function(xhr, invalidErrors) { - if (Number(xhr.status) === 422 && invalidErrors.image_file) { - this.hideUploadLoadingAnimation(); + this.$el.data("gallery-loaded", true); + }.bind(this), + error: this.imageUploadFailed.bind(this) + }); + }; - if (this.validation) this.validation.remove(); + // Delete image + Bootsy.Modal.prototype.deleteImage = function(id) { + var image = this.$el.find('.bootsy-image[data-id="' + id + '"]'); - this.validation = $("

"); - this.validation.text(invalidErrors.image_file[0]); - this.$el.find('.bootsy-upload-form').append(this.validation); - } else { this.hideGalleryLoadingAnimation(); - alert($.fn.wysihtml5.locale[this.area.locale].bootsy.error); - } - - this.showRefreshButton(); -}; - -// Add image to gallery -Bootsy.Modal.prototype.addImage = function(html) { - this.hideEmptyAlert(); - - $(html).hide().appendTo(this.$el.find('.bootsy-gallery')).fadeIn(200); -}; - -// Set image gallery -Bootsy.Modal.prototype.requestImageGallery = function() { - this.hideRefreshButton(); - this.showGalleryLoadingAnimation(); - - $.ajax({ - url: '/bootsy/images', - type: 'GET', - cache: false, - data: { - image_gallery_id: this.area.$el.data('gallery-id') - }, - dataType: 'json', - success: function(data) { - this.hideRefreshButton(); - this.hideGalleryLoadingAnimation(); - this.$el.find('.bootsy-gallery .bootsy-image').remove(); - - $.each(data.images, function(index, value) { - this.addImage(value); - }.bind(this)); - - if (data.images.length === 0) this.showEmptyAlert(); - - this.setUploadForm(data.form); - - this.$el.data('gallery-loaded', true); - }.bind(this), - error: this.imageUploadFailed.bind(this) - }); -}; - -// Delete image -Bootsy.Modal.prototype.deleteImage = function(id) { - var image = this.$el.find('.bootsy-image[data-id="' + id + '"]'); - - this.hideGalleryLoadingAnimation(); - image.hide(200, function() { - image.remove(); + image.hide( + 200, + function() { + image.remove(); - if (this.$el.find('.bootsy-image').length === 0 ) this.showEmptyAlert(); - }.bind(this)); -}; + if (this.$el.find(".bootsy-image").length === 0) this.showEmptyAlert(); + }.bind(this) + ); + }; +})(jQuery); diff --git a/app/assets/javascripts/bootsy/vendor/bootstrap.file-input.js b/app/assets/javascripts/bootsy/vendor/bootstrap.file-input.js index 65537f15..bd0cf1e1 100644 --- a/app/assets/javascripts/bootsy/vendor/bootstrap.file-input.js +++ b/app/assets/javascripts/bootsy/vendor/bootstrap.file-input.js @@ -10,113 +10,119 @@ Browse */ -$(function() { - -$.fn.bootstrapFileInput = function() { - - this.each(function(i,elem){ - - var $elem = $(elem); - - // Maybe some fields don't need to be standardized. - if (typeof $elem.attr('data-bfi-disabled') != 'undefined') { - return; - } - - // Set the word to be displayed on the button - var buttonWord = 'Browse'; - - if (typeof $elem.attr('title') != 'undefined') { - buttonWord = $elem.attr('title'); - } - - // Start by getting the HTML of the input element. - // Thanks for the tip http://stackoverflow.com/a/1299069 - var input = $('

').append( $elem.eq(0).clone() ).html(); - var className = ''; - - if (!!$elem.attr('class')) { - className = ' ' + $elem.attr('class'); - } - - // Now we're going to replace that input field with a Bootstrap button. - // The input will actually still be there, it will just be float above and transparent (done with the CSS). - $elem.replaceWith(''+buttonWord+input+''); - }) - - // After we have found all of the file inputs let's apply a listener for tracking the mouse movement. - // This is important because the in order to give the illusion that this is a button in FF we actually need to move the button from the file input under the cursor. Ugh. - .promise().done( function(){ - - // As the cursor moves over our new Bootstrap button we need to adjust the position of the invisible file input Browse button to be under the cursor. - // This gives us the pointer cursor that FF denies us - $('.file-input-wrapper').mousemove(function(cursor) { - - var input, wrapper, - wrapperX, wrapperY, - inputWidth, inputHeight, - cursorX, cursorY; - - // This wrapper element (the button surround this file input) - wrapper = $(this); - // The invisible file input element - input = wrapper.find("input"); - // The left-most position of the wrapper - wrapperX = wrapper.offset().left; - // The top-most position of the wrapper - wrapperY = wrapper.offset().top; - // The with of the browsers input field - inputWidth= input.width(); - // The height of the browsers input field - inputHeight= input.height(); - //The position of the cursor in the wrapper - cursorX = cursor.pageX; - cursorY = cursor.pageY; - - //The positions we are to move the invisible file input - // The 20 at the end is an arbitrary number of pixels that we can shift the input such that cursor is not pointing at the end of the Browse button but somewhere nearer the middle - moveInputX = cursorX - wrapperX - inputWidth + 20; - // Slides the invisible input Browse button to be positioned middle under the cursor - moveInputY = cursorY- wrapperY - (inputHeight/2); - - // Apply the positioning styles to actually move the invisible file input - input.css({ - left:moveInputX, - top:moveInputY - }); - }); - - $('.file-input-wrapper input[type=file]').change(function(){ - - var fileName; - fileName = $(this).val(); - - // Remove any previous file names - $(this).parent().next('.file-input-name').remove(); - if (!!$(this).prop('files') && $(this).prop('files').length > 1) { - fileName = $(this)[0].files.length+' files'; - //$(this).parent().after(''+$(this)[0].files.length+' files'); - } - else { - // var fakepath = 'C:\\fakepath\\'; - // fileName = $(this).val().replace('C:\\fakepath\\',''); - fileName = fileName.substring(fileName.lastIndexOf('\\')+1,fileName.length); +jQuery(function($) { + $.fn.bootstrapFileInput = function() { + this.each(function(i, elem) { + var $elem = $(elem); + + // Maybe some fields don't need to be standardized. + if (typeof $elem.attr("data-bfi-disabled") != "undefined") { + return; } - $(this).parent().after(''+fileName+''); - }); + // Set the word to be displayed on the button + var buttonWord = "Browse"; - }); + if (typeof $elem.attr("title") != "undefined") { + buttonWord = $elem.attr("title"); + } -}; + // Start by getting the HTML of the input element. + // Thanks for the tip http://stackoverflow.com/a/1299069 + var input = $("
").append($elem.eq(0).clone()).html(); + var className = ""; -// Add the styles before the first stylesheet -// This ensures they can be easily overridden with developer styles -var cssHtml = ''; -$('link[rel=stylesheet]').eq(0).before(cssHtml); + if (!!$elem.attr("class")) { + className = " " + $elem.attr("class"); + } + // Now we're going to replace that input field with a Bootstrap button. + // The input will actually still be there, it will just be float above and transparent (done with the CSS). + $elem.replaceWith( + '' + + buttonWord + + input + + "" + ); + }) + // After we have found all of the file inputs let's apply a listener for tracking the mouse movement. + // This is important because the in order to give the illusion that this is a button in FF we actually need to move the button from the file input under the cursor. Ugh. + .promise() + .done(function() { + // As the cursor moves over our new Bootstrap button we need to adjust the position of the invisible file input Browse button to be under the cursor. + // This gives us the pointer cursor that FF denies us + $(".file-input-wrapper").mousemove(function(cursor) { + var input, + wrapper, + wrapperX, + wrapperY, + inputWidth, + inputHeight, + cursorX, + cursorY; + + // This wrapper element (the button surround this file input) + wrapper = $(this); + // The invisible file input element + input = wrapper.find("input"); + // The left-most position of the wrapper + wrapperX = wrapper.offset().left; + // The top-most position of the wrapper + wrapperY = wrapper.offset().top; + // The with of the browsers input field + inputWidth = input.width(); + // The height of the browsers input field + inputHeight = input.height(); + //The position of the cursor in the wrapper + cursorX = cursor.pageX; + cursorY = cursor.pageY; + + //The positions we are to move the invisible file input + // The 20 at the end is an arbitrary number of pixels that we can shift the input such that cursor is not pointing at the end of the Browse button but somewhere nearer the middle + moveInputX = cursorX - wrapperX - inputWidth + 20; + // Slides the invisible input Browse button to be positioned middle under the cursor + moveInputY = cursorY - wrapperY - inputHeight / 2; + + // Apply the positioning styles to actually move the invisible file input + input.css({ + left: moveInputX, + top: moveInputY + }); + }); + + $(".file-input-wrapper input[type=file]").change(function() { + var fileName; + fileName = $(this).val(); + + // Remove any previous file names + $(this).parent().next(".file-input-name").remove(); + if (!!$(this).prop("files") && $(this).prop("files").length > 1) { + fileName = $(this)[0].files.length + " files"; + //$(this).parent().after(''+$(this)[0].files.length+' files'); + } else { + // var fakepath = 'C:\\fakepath\\'; + // fileName = $(this).val().replace('C:\\fakepath\\',''); + fileName = fileName.substring( + fileName.lastIndexOf("\\") + 1, + fileName.length + ); + } + + $(this) + .parent() + .after('' + fileName + ""); + }); + }); + }; + + // Add the styles before the first stylesheet + // This ensures they can be easily overridden with developer styles + var cssHtml = ""; + $("link[rel=stylesheet]").eq(0).before(cssHtml); });