From 109da3a297742034d241ef0a9fbba3df3aa49267 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Thu, 18 Apr 2013 10:59:15 -0700 Subject: [PATCH] Implementing Media Library module --HG-- branch : 1.x --- .../Media/Services/MediaServiceTests.cs | 5 + src/Orchard.Web/Core/Contents/Shapes.cs | 6 +- src/Orchard.Web/Core/Shapes/Scripts/base.js | 2 +- src/Orchard.Web/Media/web.config | 8 - .../Controllers/AdminController.cs | 100 + .../Drivers/ImageEditorCropPartDriver.cs | 14 + .../Drivers/ImageEditorEffectsPartDriver.cs | 14 + .../Drivers/ImageEditorFilterPartDriver.cs | 14 + .../Drivers/ImageEditorResizePartDriver.cs | 14 + .../Drivers/ImagePartDriver.cs | 11 + .../Modules/Orchard.ImageEditor/Migrations.cs | 13 + .../Models/ImageEditorPart.cs | 9 + .../Modules/Orchard.ImageEditor/Module.txt | 12 + .../Orchard.ImageEditor.csproj | 192 ++ .../Orchard.ImageEditor/Placement.info | 22 + .../Properties/AssemblyInfo.cs | 36 + .../Orchard.ImageEditor/Scripts/Web.config | 25 + .../Scripts/caman/caman.full.min.js | 212 +++ .../Scripts/image.editor-crop.js | 98 + .../Scripts/image.editor.js | 84 + .../Scripts/jcrop/MIT-LICENSE.txt | 22 + .../Scripts/jcrop/js/jquery.Jcrop.js | 1691 +++++++++++++++++ .../Scripts/jcrop/js/jquery.Jcrop.min.js | 2 + .../Scripts/jcrop/js/jquery.Jcrop.min.js.map | 8 + .../Orchard.ImageEditor/Styles/Web.config | 25 + .../Styles/image-editor.css | 57 + .../Styles/jcrop/css/Jcrop.gif | Bin 0 -> 329 bytes .../Styles/jcrop/css/jquery.Jcrop.css | 165 ++ .../Styles/jcrop/css/jquery.Jcrop.min.css | 29 + .../Styles/orchard-imageeditor-admin.css | 435 +++++ .../Views/Admin/Edit.cshtml | 24 + .../Views/Content-ImageEditor.cshtml | 50 + .../Views/Parts/Image.Editor.Crop.cshtml | 7 + .../Parts/Image.Editor.CropOptions.cshtml | 26 + .../Views/Parts/Image.Editor.Effects.cshtml | 101 + .../Parts/Image.Editor.EffectsOptions.cshtml | 28 + .../Views/Parts/Image.Editor.Filter.cshtml | 120 ++ .../Parts/Image.Editor.FilterOptions.cshtml | 63 + .../Views/Parts/Image.Editor.Resize.cshtml | 82 + .../Parts/Image.Editor.ResizeOptions.cshtml | 28 + .../Views/Parts/Image.Editor.cshtml | 8 + .../Orchard.ImageEditor/Views/Web.config | 41 + .../Modules/Orchard.ImageEditor/Web.config | 41 + .../Modules/Orchard.Media/AdminMenu.cs | 2 +- .../Modules/Orchard.MediaLibrary/AdminMenu.cs | 21 + .../Controllers/AdminController.cs | 100 + .../Controllers/ClientStorageController.cs | 55 + .../Controllers/FolderController.cs | 143 ++ .../Controllers/WebSearchController.cs | 47 + .../Drivers/AudioPartDriver.cs | 15 + .../Drivers/DocumentPartDriver.cs | 15 + .../Drivers/ImagePartDriver.cs | 16 + .../Drivers/MediaLibraryPickerFieldDriver.cs | 101 + .../Drivers/MediaPartDriver.cs | 22 + .../Drivers/VideoPartDriver.cs | 15 + .../Factories/AudioFactory.cs | 66 + .../Factories/DocumentFactory.cs | 65 + .../Factories/IMediaFactory.cs | 20 + .../Factories/IMediaFactorySelector.cs | 7 + .../Factories/ImageFactory.cs | 70 + .../Factories/MediaFactorySelectorResult.cs | 6 + .../Factories/VideoFactory.cs | 67 + .../Fields/MediaLibrayPickerField.cs | 41 + .../MediaLibraryPickerFieldHandler.cs | 37 + .../Handlers/MediaPartHandler.cs | 24 + .../Orchard.MediaLibrary/Migrations.cs | 71 + .../Orchard.MediaLibrary/Models/AudioPart.cs | 13 + .../Models/DocumentPart.cs | 13 + .../Orchard.MediaLibrary/Models/ImagePart.cs | 19 + .../Models/MediaFolder.cs | 17 + .../Orchard.MediaLibrary/Models/MediaPart.cs | 43 + .../Models/MediaPartRecord.cs | 13 + .../Orchard.MediaLibrary/Models/VideoPart.cs | 13 + .../Modules/Orchard.MediaLibrary/Module.txt | 13 + .../Orchard.MediaLibrary.csproj | 326 ++++ .../Orchard.MediaLibrary/Permissions.cs | 41 + .../Orchard.MediaLibrary/Placement.info | 85 + .../Properties/AssemblyInfo.cs | 36 + .../ClientStorage/ClientStorageMenu.cs | 21 + .../Providers/WebSearchMenu.cs | 21 + .../Orchard.MediaLibrary/ResourceManifest.cs | 9 + .../Orchard.MediaLibrary/Scripts/Web.config | 25 + .../Orchard.MediaLibrary/Scripts/history.js | 1 + .../Scripts/knockout-2.2.1.js | 85 + .../Services/IMediaLibraryService.cs | 32 + .../Services/MediaLibraryService.cs | 196 ++ .../Orchard.MediaLibrary/Services/Shapes.cs | 43 + .../MediaLibraryPickerFieldEditorEvents.cs | 35 + .../MediaLibraryPickerFieldSettings.cs | 9 + .../Styles/Images/ajax-loader.gif | Bin 0 -> 847 bytes .../Styles/Images/folders-loader.gif | Bin 0 -> 5886 bytes .../Styles/Images/loading.gif | Bin 0 -> 1688 bytes .../Styles/Images/processing.gif | Bin 0 -> 3209 bytes .../Orchard.MediaLibrary/Styles/Web.config | 25 + .../Styles/dialog-mode.css | 7 + .../Styles/media-library-picker-admin.css | 51 + .../menu.clientstorage-mediaproviders.css | 3 + .../Styles/menu.websearch-mediaproviders.css | 3 + .../Styles/orchard-clientstorage-admin.css | 94 + .../Styles/orchard-medialibrary-admin.css | 362 ++++ .../Styles/orchard-mediaproviders-admin.css | 164 ++ .../Styles/orchard-websearch-admin.css | 158 ++ .../MediaLibraryPickerFieldViewModel.cs | 14 + .../MediaManagerFolderCreateViewModel.cs | 10 + .../MediaManagerFolderEditViewModel.cs | 12 + .../ViewModels/MediaManagerImportViewModel.cs | 12 + .../ViewModels/MediaManagerIndexViewModel.cs | 11 + .../MediaManagerMediaItemsViewModel.cs | 15 + .../Views/Admin/Import.cshtml | 63 + .../Views/Admin/Index.cshtml | 403 ++++ .../Views/Admin/MediaItems.cshtml | 24 + .../Views/Admin/MediaManagerFolder.cshtml | 17 + .../Views/ClientStorage/Index.cshtml | 151 ++ .../MediaLibraryPickerFieldSettings.cshtml | 27 + .../Fields/MediaLibraryPicker.Edit.cshtml | 129 ++ .../EditorTemplates/Parts.Media.Edit.cshtml | 13 + .../MediaLibraryPicker.SummaryAdmin.cshtml | 33 + .../Views/Fields/MediaLibraryPicker.cshtml | 18 + .../Views/Folder/Create.cshtml | 25 + .../Views/Folder/Edit.cshtml | 28 + .../Views/Media-Audio.Thumbnail.cshtml | 12 + .../Views/Media-Document.Thumbnail.cshtml | 11 + .../Views/Media-Image.Thumbnail.cshtml | 11 + .../Views/Media-Video.Thumbnail.cshtml | 12 + .../Views/Media.Edit.cshtml | 8 + .../Views/Media.SummaryAdmin.cshtml | 23 + .../Views/Media.Thumbnail.cshtml | 10 + .../Orchard.MediaLibrary/Views/Media.cshtml | 23 + .../Views/Parts/Audio.Metadata.cshtml | 9 + .../Views/Parts/Audio.Summary.cshtml | 8 + .../Views/Parts/Audio.SummaryAdmin.cshtml | 8 + .../Views/Parts/Audio.cshtml | 8 + .../Views/Parts/Document.Metadata.cshtml | 10 + .../Views/Parts/Document.Summary.cshtml | 11 + .../Views/Parts/Document.SummaryAdmin.cshtml | 11 + .../Views/Parts/Document.cshtml | 11 + .../Views/Parts/Image.Metadata.cshtml | 10 + .../Views/Parts/Image.Summary.cshtml | 12 + .../Views/Parts/Image.SummaryAdmin.cshtml | 10 + .../Views/Parts/Image.cshtml | 9 + .../Views/Parts/Media.Actions.cshtml | 11 + .../Views/Parts/Media.SummaryAdmin.cshtml | 31 + .../Views/Parts/Video.Metadata.cshtml | 10 + .../Views/Parts/Video.Summary.cshtml | 8 + .../Views/Parts/Video.SummaryAdmin.cshtml | 8 + .../Views/Parts/Video.cshtml | 8 + .../Orchard.MediaLibrary/Views/Web.config | 41 + .../Views/WebSearch/Index.cshtml | 227 +++ .../Modules/Orchard.MediaLibrary/Web.config | 41 + .../Media/StorageProviderExtensions.cs | 17 +- .../ImageProcessingFileNameProvider.cs | 31 +- .../Shapes/MediaShapes.cs | 156 +- .../Orchard.Users/Orchard.Users.csproj | 8 +- .../Orchard.jQuery/Orchard.jQuery.csproj | 15 + .../Orchard.jQuery/ResourceManifest.cs | 8 + .../Scripts/jquery.colorbox-min.js | 6 + .../Orchard.jQuery/Scripts/jquery.colorbox.js | 1020 ++++++++++ .../Scripts/jquery.fileupload.js | 1233 ++++++++++++ .../Scripts/jquery.fileupload.min.js | 2 + .../Scripts/jquery.iframe-transport.js | 185 ++ .../Scripts/jquery.iframe-transport.min.js | 2 + .../Orchard.jQuery/Styles/colorbox.css | 57 + .../Styles/images/colorbox/border.png | Bin 0 -> 163 bytes .../Styles/images/colorbox/controls.png | Bin 0 -> 2033 bytes .../Styles/images/colorbox/loading.gif | Bin 0 -> 9427 bytes .../images/colorbox/loading_background.png | Bin 0 -> 166 bytes .../TinyMce/Scripts/orchard-tinymce.js | 4 +- .../plugins/imageeditor/editor_plugin.js | 2 + .../plugins/imageeditor/editor_plugin_src.js | 107 ++ .../imageeditor/editor_plugin_src.min.js | 2 + .../imageeditor/editor_plugin_src.min.js.map | 8 + .../plugins/imageeditor/img/picture_edit.png | Bin 0 -> 646 bytes .../Modules/TinyMce/TinyMce.csproj | 12 +- .../TinyMce/Views/Body-Html.Editor.cshtml | 3 + .../Themes/TheAdmin/Views/Menu.cshtml | 13 +- src/Orchard.Web/Web.config | 2 +- src/Orchard.sln | 23 + src/Orchard/ContentManagement/ContentPart.cs | 4 +- .../InfosetStorage/InfosetPart.cs | 43 +- .../Media/ConfigurationMimeTypeProvider.cs | 71 + .../Media/FileSystemStorageProvider.cs | 16 +- .../FileSystems/Media/IMimeTypeProvider.cs | 5 + .../FileSystems/Media/IStorageProvider.cs | 7 + src/Orchard/Mvc/Html/ContentItemExtensions.cs | 4 +- .../Mvc/ViewEngines/Razor/WebViewPage.cs | 10 + src/Orchard/Orchard.Framework.csproj | 2 + 186 files changed, 11544 insertions(+), 97 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Controllers/AdminController.cs create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorCropPartDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorEffectsPartDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorFilterPartDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorResizePartDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImagePartDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Migrations.cs create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Models/ImageEditorPart.cs create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Module.txt create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Orchard.ImageEditor.csproj create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Placement.info create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Properties/AssemblyInfo.cs create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/Web.config create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/caman/caman.full.min.js create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/image.editor-crop.js create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/image.editor.js create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/jcrop/MIT-LICENSE.txt create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/jcrop/js/jquery.Jcrop.js create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/jcrop/js/jquery.Jcrop.min.js create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/jcrop/js/jquery.Jcrop.min.js.map create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/Web.config create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/image-editor.css create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/Jcrop.gif create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/jquery.Jcrop.css create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/jquery.Jcrop.min.css create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/orchard-imageeditor-admin.css create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Admin/Edit.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Content-ImageEditor.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Crop.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.CropOptions.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Effects.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.EffectsOptions.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Filter.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.FilterOptions.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Resize.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.ResizeOptions.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Web.config create mode 100644 src/Orchard.Web/Modules/Orchard.ImageEditor/Web.config create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/AdminMenu.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/FolderController.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/WebSearchController.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryPickerFieldDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/AudioFactory.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/DocumentFactory.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/IMediaFactory.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/IMediaFactorySelector.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/ImageFactory.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/MediaFactorySelectorResult.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/VideoFactory.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Fields/MediaLibrayPickerField.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaLibraryPickerFieldHandler.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Migrations.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/AudioPart.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/DocumentPart.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/ImagePart.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaFolder.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPart.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPartRecord.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/VideoPart.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Permissions.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Placement.info create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Properties/AssemblyInfo.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/ClientStorage/ClientStorageMenu.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/WebSearchMenu.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/ResourceManifest.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/Web.config create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/history.js create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/knockout-2.2.1.js create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/IMediaLibraryService.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/MediaLibraryService.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/Shapes.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Settings/MediaLibraryPickerFieldEditorEvents.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Settings/MediaLibraryPickerFieldSettings.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/Images/ajax-loader.gif create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/Images/folders-loader.gif create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/Images/loading.gif create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/Images/processing.gif create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/Web.config create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/dialog-mode.css create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/media-library-picker-admin.css create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/menu.clientstorage-mediaproviders.css create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/menu.websearch-mediaproviders.css create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/orchard-clientstorage-admin.css create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/orchard-medialibrary-admin.css create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/orchard-mediaproviders-admin.css create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/orchard-websearch-admin.css create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/ViewModels/MediaLibraryPickerFieldViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/ViewModels/MediaManagerFolderCreateViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/ViewModels/MediaManagerFolderEditViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/ViewModels/MediaManagerImportViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/ViewModels/MediaManagerIndexViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/ViewModels/MediaManagerMediaItemsViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Import.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaItems.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaManagerFolder.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/ClientStorage/Index.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/DefinitionTemplates/MediaLibraryPickerFieldSettings.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Fields/MediaLibraryPicker.Edit.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Parts.Media.Edit.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Fields/MediaLibraryPicker.SummaryAdmin.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Fields/MediaLibraryPicker.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Create.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Edit.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Audio.Thumbnail.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Document.Thumbnail.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Image.Thumbnail.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Video.Thumbnail.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.Edit.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.SummaryAdmin.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.Thumbnail.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.Metadata.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.Summary.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.SummaryAdmin.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.Metadata.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.Summary.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.SummaryAdmin.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.Metadata.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.Summary.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.SummaryAdmin.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Media.Actions.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Media.SummaryAdmin.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.Metadata.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.Summary.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.SummaryAdmin.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Web.config create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/WebSearch/Index.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.MediaLibrary/Web.config create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.colorbox-min.js create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.colorbox.js create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.fileupload.js create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.fileupload.min.js create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.iframe-transport.js create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.iframe-transport.min.js create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Styles/colorbox.css create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Styles/images/colorbox/border.png create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Styles/images/colorbox/controls.png create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Styles/images/colorbox/loading.gif create mode 100644 src/Orchard.Web/Modules/Orchard.jQuery/Styles/images/colorbox/loading_background.png create mode 100644 src/Orchard.Web/Modules/TinyMce/Scripts/plugins/imageeditor/editor_plugin.js create mode 100644 src/Orchard.Web/Modules/TinyMce/Scripts/plugins/imageeditor/editor_plugin_src.js create mode 100644 src/Orchard.Web/Modules/TinyMce/Scripts/plugins/imageeditor/editor_plugin_src.min.js create mode 100644 src/Orchard.Web/Modules/TinyMce/Scripts/plugins/imageeditor/editor_plugin_src.min.js.map create mode 100644 src/Orchard.Web/Modules/TinyMce/Scripts/plugins/imageeditor/img/picture_edit.png create mode 100644 src/Orchard/FileSystems/Media/ConfigurationMimeTypeProvider.cs create mode 100644 src/Orchard/FileSystems/Media/IMimeTypeProvider.cs diff --git a/src/Orchard.Tests.Modules/Media/Services/MediaServiceTests.cs b/src/Orchard.Tests.Modules/Media/Services/MediaServiceTests.cs index 8fee76137..6faf4cef3 100644 --- a/src/Orchard.Tests.Modules/Media/Services/MediaServiceTests.cs +++ b/src/Orchard.Tests.Modules/Media/Services/MediaServiceTests.cs @@ -271,6 +271,11 @@ namespace Orchard.Tests.Modules.Media.Services { public void SaveStream(string path, Stream inputStream) { SavedStreams.Add(path); } + + + public string GetLocalPath(string url) { + throw new NotImplementedException(); + } } private class StubStorageFolder : IStorageFolder { diff --git a/src/Orchard.Web/Core/Contents/Shapes.cs b/src/Orchard.Web/Core/Contents/Shapes.cs index 6d48a4c91..94aaa7085 100644 --- a/src/Orchard.Web/Core/Contents/Shapes.cs +++ b/src/Orchard.Web/Core/Contents/Shapes.cs @@ -20,17 +20,15 @@ namespace Orchard.Core.Contents { displaying.ShapeMetadata.Alternates.Add("Content_" + EncodeAlternateElement(displaying.ShapeMetadata.DisplayType)); // Content__[ContentType] e.g. Content-BlogPost, - // adjusted to Content_[DisplayType]__[ContentType], e.g. Content.Summary-BlogPost displaying.ShapeMetadata.Alternates.Add("Content__" + EncodeAlternateElement(contentItem.ContentType)); // Content__[Id] e.g. Content-42, - // adjusted to Content_[DisplayType]__[Id], e.g. Content.Summary-42 displaying.ShapeMetadata.Alternates.Add("Content__" + contentItem.Id); - // Content_[DisplayType]__[ContentType] e.g. Content.Summary-BlogPost + // Content_[DisplayType]__[ContentType] e.g. Content-BlogPost.Summary displaying.ShapeMetadata.Alternates.Add("Content_" + displaying.ShapeMetadata.DisplayType + "__" + EncodeAlternateElement(contentItem.ContentType)); - // Content_[DisplayType]__[Id] e.g. Content.Summary-42 + // Content_[DisplayType]__[Id] e.g. Content-42.Summary displaying.ShapeMetadata.Alternates.Add("Content_" + displaying.ShapeMetadata.DisplayType + "__" + contentItem.Id); } }); diff --git a/src/Orchard.Web/Core/Shapes/Scripts/base.js b/src/Orchard.Web/Core/Shapes/Scripts/base.js index 58e4b761e..afb6e250b 100644 --- a/src/Orchard.Web/Core/Shapes/Scripts/base.js +++ b/src/Orchard.Web/Core/Shapes/Scripts/base.js @@ -223,7 +223,7 @@ $(function () { var magicToken = $("input[name=__RequestVerificationToken]").first(); if (!magicToken) { return; } // no sense in continuing if form POSTS will fail - $("a[itemprop~=UnsafeUrl]").each(function () { + $("a[itemprop~=UnsafeUrl]").on("click", function () { var _this = $(this); var hrefParts = _this.attr("href").split("?"); var form = $("
"); diff --git a/src/Orchard.Web/Media/web.config b/src/Orchard.Web/Media/web.config index c964db718..c31c0d75f 100644 --- a/src/Orchard.Web/Media/web.config +++ b/src/Orchard.Web/Media/web.config @@ -13,13 +13,5 @@ - - - - - diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Controllers/AdminController.cs new file mode 100644 index 000000000..d20c05c3c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Controllers/AdminController.cs @@ -0,0 +1,100 @@ +using System; +using System.IO; +using System.Linq; +using System.Web.Mvc; +using Orchard.ContentManagement; +using Orchard.FileSystems.Media; +using Orchard.ImageEditor.Models; +using Orchard.MediaLibrary.Models; +using Orchard.Mvc; +using Orchard.Themes; +using Orchard.UI.Admin; + +namespace Orchard.ImageEditor.Controllers { + [Admin] + public class AdminController : Controller { + private readonly IStorageProvider _storageProvider; + + public AdminController(IOrchardServices orchardServices, IStorageProvider storageProvider) { + _storageProvider = storageProvider; + Services = orchardServices; + } + + public IOrchardServices Services { get; set; } + + public ActionResult Index(int id) { + var media = Services.ContentManager.Get(id).As(); + + if (media == null) { + return HttpNotFound(); + } + + var contentItem = Services.ContentManager.New("ImageEditor").As(); + + contentItem.ImagePart = media.As(); + contentItem.MediaPart = media.As(); + + var shape = Services.ContentManager.BuildDisplay(contentItem); + shape.MediaContentItem(media.ContentItem); + + return new ShapeResult(this, shape); + } + + [Themed(false)] + public ActionResult Edit(string src) { + var localPath = _storageProvider.GetLocalPath(src); + + if (_storageProvider.GetFile(localPath) == null) { + return HttpNotFound(); + } + + var media = Services.ContentManager.Query().Where(x => x.Resource == src).Slice(0, 1).FirstOrDefault(); + + if (media == null) { + return HttpNotFound(); + } + + var contentItem = Services.ContentManager.New("ImageEditor").As(); + + contentItem.ImagePart = media.As(); + contentItem.MediaPart = media.As(); + + var shape = Services.ContentManager.BuildDisplay(contentItem); + shape.MediaContentItem(media.ContentItem); + + return View(shape); + } + + [HttpPost] + public ActionResult Upload(int id, string content, int width, int height) { + var media = Services.ContentManager.Get(id).As(); + + if (media == null) { + return HttpNotFound(); + } + + const string signature = "data:image/png;base64,"; + + if (!content.StartsWith(signature, StringComparison.OrdinalIgnoreCase)) { + return HttpNotFound(); + } + + var image = media.As(); + + content = content.Substring(signature.Length); + + var buffer = Convert.FromBase64String(content); + var localPath = _storageProvider.GetLocalPath(media.Resource); + _storageProvider.DeleteFile(localPath); + using (var stream = new MemoryStream(buffer)) { + _storageProvider.SaveStream(localPath, stream); + } + + image.Width = width; + image.Height = height; + media.MimeType = "image/png"; + + return Json(true); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorCropPartDriver.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorCropPartDriver.cs new file mode 100644 index 000000000..75bfc4f97 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorCropPartDriver.cs @@ -0,0 +1,14 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.ImageEditor.Models; + +namespace Orchard.ImageEditor.Drivers { + public class ImageEditorCropPartDriver : ContentPartDriver { + + protected override DriverResult Display(ImageEditorPart part, string displayType, dynamic shapeHelper) { + return Combined( + ContentShape("Parts_Image_Editor_Crop", () => shapeHelper.Parts_Image_Editor_Crop()), + ContentShape("Parts_Image_Editor_CropOptions", () => shapeHelper.Parts_Image_Editor_CropOptions()) + ); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorEffectsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorEffectsPartDriver.cs new file mode 100644 index 000000000..8aa61a6bd --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorEffectsPartDriver.cs @@ -0,0 +1,14 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.ImageEditor.Models; + +namespace Orchard.ImageEditor.Drivers { + public class ImageEditorEffectsPartDriver : ContentPartDriver { + + protected override DriverResult Display(ImageEditorPart part, string displayType, dynamic shapeHelper) { + return Combined( + ContentShape("Parts_Image_Editor_Effects", () => shapeHelper.Parts_Image_Editor_Effects()), + ContentShape("Parts_Image_Editor_EffectsOptions", () => shapeHelper.Parts_Image_Editor_EffectsOptions()) + ); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorFilterPartDriver.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorFilterPartDriver.cs new file mode 100644 index 000000000..b0ffc85f3 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorFilterPartDriver.cs @@ -0,0 +1,14 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.ImageEditor.Models; + +namespace Orchard.ImageEditor.Drivers { + public class ImageEditorFilterPartDriver : ContentPartDriver { + + protected override DriverResult Display(ImageEditorPart part, string displayType, dynamic shapeHelper) { + return Combined( + ContentShape("Parts_Image_Editor_Filter", () => shapeHelper.Parts_Image_Editor_Filter()), + ContentShape("Parts_Image_Editor_FilterOptions", () => shapeHelper.Parts_Image_Editor_FilterOptions()) + ); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorResizePartDriver.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorResizePartDriver.cs new file mode 100644 index 000000000..3c416fa6d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImageEditorResizePartDriver.cs @@ -0,0 +1,14 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.ImageEditor.Models; + +namespace Orchard.ImageEditor.Drivers { + public class ImageEditorResizePartDriver : ContentPartDriver { + + protected override DriverResult Display(ImageEditorPart part, string displayType, dynamic shapeHelper) { + return Combined( + ContentShape("Parts_Image_Editor_Resize", () => shapeHelper.Parts_Image_Editor_Resize()), + ContentShape("Parts_Image_Editor_ResizeOptions", () => shapeHelper.Parts_Image_Editor_ResizeOptions()) + ); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImagePartDriver.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImagePartDriver.cs new file mode 100644 index 000000000..1b4aa2562 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Drivers/ImagePartDriver.cs @@ -0,0 +1,11 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.MediaLibrary.Models; + +namespace Orchard.ImageEditor.Drivers { + public class ImagePartDriver : ContentPartDriver { + + protected override DriverResult Display(ImagePart part, string displayType, dynamic shapeHelper) { + return ContentShape("Parts_Image_Editor", () => shapeHelper.Parts_Image_Editor()); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Migrations.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Migrations.cs new file mode 100644 index 000000000..569e54c5b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Migrations.cs @@ -0,0 +1,13 @@ +using Orchard.ContentManagement.MetaData; +using Orchard.Core.Contents.Extensions; +using Orchard.Data.Migration; + +namespace Orchard.ImageEditor { + public class Migrations : DataMigrationImpl { + + public int Create() { + ContentDefinitionManager.AlterTypeDefinition("ImageEditor", t => t.WithPart("ImageEditorPart")); + return 1; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Models/ImageEditorPart.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Models/ImageEditorPart.cs new file mode 100644 index 000000000..199bb0c06 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Models/ImageEditorPart.cs @@ -0,0 +1,9 @@ +using Orchard.ContentManagement; +using Orchard.MediaLibrary.Models; + +namespace Orchard.ImageEditor.Models { + public class ImageEditorPart : ContentPart { + public MediaPart MediaPart { get; set; } + public ImagePart ImagePart { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Module.txt b/src/Orchard.Web/Modules/Orchard.ImageEditor/Module.txt new file mode 100644 index 000000000..1329e6e42 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Module.txt @@ -0,0 +1,12 @@ +Name: Image Editor +AntiForgery: enabled +Author: The Orchard Team +Website: http://orchardproject.net +Version: 1.0 +OrchardVersion: 1.0 +Description: Description for the module +Features: + Orchard.ImageEditor: + Description: Description for feature Orchard.ImageEditor. + Dependencies: Orchard.MediaLibrary + Category: Media \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Orchard.ImageEditor.csproj b/src/Orchard.Web/Modules/Orchard.ImageEditor/Orchard.ImageEditor.csproj new file mode 100644 index 000000000..662a3864e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Orchard.ImageEditor.csproj @@ -0,0 +1,192 @@ + + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {1F0B6B85-8B0B-47CA-899D-F25B4F1B52C3} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Orchard.ImageEditor + Orchard.ImageEditor + v4.0 + false + + + 4.0 + + + false + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\ + TRACE + prompt + 4 + AllRules.ruleset + + + + + + + 3.5 + + + + False + ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} + Orchard.Framework + + + {9916839C-39FC-4CEB-A5AF-89CA7E87119F} + Orchard.Core + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + jquery.Jcrop.js + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + $(ProjectDir)\..\Manifests + + + + + + + + + + + + False + True + 45979 + / + + + False + True + http://orchard.codeplex.com + False + + + + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Placement.info b/src/Orchard.Web/Modules/Orchard.ImageEditor/Placement.info new file mode 100644 index 000000000..333392099 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Placement.info @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.ImageEditor/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..083fe4117 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Orchard.ImageEditor")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyProduct("Orchard")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ea4d97f6-5060-44e7-bd56-1da671421bf3")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/Web.config b/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/Web.config new file mode 100644 index 000000000..770adfab5 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/Web.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/caman/caman.full.min.js b/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/caman/caman.full.min.js new file mode 100644 index 000000000..1f6c92b0e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/caman/caman.full.min.js @@ -0,0 +1,212 @@ + +(function(){var $,Analyze,Blender,Calculate,Caman,CamanParser,Canvas,Convert,Event,Fiber,Filter,IO,Image,Layer,Log,Logger,PixelInfo,Plugin,Renderer,Root,Store,Util,fs,slice,vignetteFilters,__hasProp={}.hasOwnProperty,__indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i255){return 255;} +return val;};Util.copyAttributes=function(from,to,opts){var attr,_i,_len,_ref,_ref1,_results;if(opts==null){opts={};} +_ref=from.attributes;_results=[];for(_i=0,_len=_ref.length;_i<_len;_i++){attr=_ref[_i];if((opts.except!=null)&&(_ref1=attr.nodeName,__indexOf.call(opts.except,_ref1)>=0)){continue;} +_results.push(to.setAttribute(attr.nodeName,attr.nodeValue));} +return _results;};return Util;})();if(typeof exports!=="undefined"&&exports!==null){Root=exports;Canvas=require('canvas');Image=Canvas.Image;Fiber=require('fibers');fs=require('fs');}else{Root=window;} +Root.Caman=Caman=(function(){Caman.version={release:"4.1.0",date:"2/12/2013"};Caman.DEBUG=false;Caman.NodeJS=typeof exports!=="undefined"&&exports!==null;Caman.autoload=!Caman.NodeJS;Caman.allowRevert=true;Caman.crossOrigin="anonymous";Caman.toString=function(){return"Version "+Caman.version.release+", Released "+Caman.version.date;};Caman.remoteProxy="";Caman.proxyParam="camanProxyUrl";Caman.getAttrId=function(canvas){if(Caman.NodeJS){return true;} +if(typeof canvas==="string"){canvas=$(canvas);} +if(!((canvas!=null)&&(canvas.getAttribute!=null))){return null;} +return canvas.getAttribute('data-caman-id');};function Caman(){var args,callback,id,_this=this;if(arguments.length===0){throw"Invalid arguments";} +if(this instanceof Caman){this.finishInit=this.finishInit.bind(this);this.imageLoaded=this.imageLoaded.bind(this);args=arguments[0];if(!Caman.NodeJS){id=parseInt(Caman.getAttrId(args[0]),10);callback=typeof args[1]==="function"?args[1]:typeof args[2]==="function"?args[2]:function(){};if(!isNaN(id)&&Store.has(id)){return Store.execute(id,callback);}} +this.id=Util.uniqid.get();this.initializedPixelData=this.originalPixelData=null;this.cropCoordinates={x:0,y:0};this.cropped=false;this.resized=false;this.pixelStack=[];this.layerStack=[];this.canvasQueue=[];this.currentLayer=null;this.scaled=false;this.analyze=new Analyze(this);this.renderer=new Renderer(this);this.domIsLoaded(function(){_this.parseArguments(args);return _this.setup();});return this;}else{return new Caman(arguments);}} +Caman.prototype.domIsLoaded=function(cb){var listener,_this=this;if(Caman.NodeJS){return setTimeout(function(){return cb.call(_this);},0);}else{if(document.readyState==="complete"){Log.debug("DOM initialized");return setTimeout(function(){return cb.call(_this);},0);}else{listener=function(){if(document.readyState==="complete"){Log.debug("DOM initialized");return cb.call(_this);}};return document.addEventListener("readystatechange",listener,false);}}};Caman.prototype.parseArguments=function(args){var key,val,_ref,_results;if(args.length===0){throw"Invalid arguments given";} +this.initObj=null;this.initType=null;this.imageUrl=null;this.callback=function(){};this.setInitObject(args[0]);if(args.length===1){return;} +switch(typeof args[1]){case"string":this.imageUrl=args[1];break;case"function":this.callback=args[1];} +if(args.length===2){return;} +this.callback=args[2];if(args.length===4){_ref=args[4];_results=[];for(key in _ref){if(!__hasProp.call(_ref,key))continue;val=_ref[key];_results.push(this.options[key]=val);} +return _results;}};Caman.prototype.setInitObject=function(obj){if(Caman.NodeJS){this.initObj=obj;this.initType='node';return;} +if(typeof obj==="object"){this.initObj=obj;}else{this.initObj=$(obj);} +return this.initType=this.initObj.nodeName.toLowerCase();};Caman.prototype.setup=function(){switch(this.initType){case"node":return this.initNode();case"img":return this.initImage();case"canvas":return this.initCanvas();}};Caman.prototype.initNode=function(){var _this=this;Log.debug("Initializing for NodeJS");this.image=new Image();this.image.onload=function(){Log.debug("Image loaded. Width = "+_this.image.width+", Height = "+_this.image.height);_this.canvas=new Canvas(_this.image.width,_this.image.height);return _this.finishInit();};this.image.onerror=function(err){throw err;};return this.image.src=this.initObj;};Caman.prototype.initImage=function(){this.image=this.initObj;this.canvas=document.createElement('canvas');this.context=this.canvas.getContext('2d');Util.copyAttributes(this.image,this.canvas,{except:['src']});this.image.parentNode.replaceChild(this.canvas,this.image);this.imageAdjustments();return this.waitForImageLoaded();};Caman.prototype.initCanvas=function(){this.canvas=this.initObj;this.context=this.canvas.getContext('2d');if(this.imageUrl!=null){this.image=document.createElement('img');this.image.src=this.imageUrl;this.imageAdjustments();return this.waitForImageLoaded();}else{return this.finishInit();}};Caman.prototype.imageAdjustments=function(){if(this.needsHiDPISwap()){Log.debug(this.image.src,"->",this.hiDPIReplacement());this.swapped=true;this.image.src=this.hiDPIReplacement();} +if(IO.isRemote(this.image)){this.image.src=IO.proxyUrl(this.image.src);return Log.debug("Remote image detected, using URL = "+this.image.src);}};Caman.prototype.waitForImageLoaded=function(){if(this.image.complete){return this.imageLoaded();}else{return this.image.onload=this.imageLoaded;}};Caman.prototype.imageLoaded=function(){Log.debug("Image loaded. Width = "+this.image.width+", Height = "+this.image.height);if(this.swapped){this.canvas.width=this.image.width/this.hiDPIRatio();this.canvas.height=this.image.height/this.hiDPIRatio();}else{this.canvas.width=this.image.width;this.canvas.height=this.image.height;} +return this.finishInit();};Caman.prototype.finishInit=function(){var i,pixel,_i,_len,_ref;if(this.context==null){this.context=this.canvas.getContext('2d');} +this.originalWidth=this.preScaledWidth=this.width=this.canvas.width;this.originalHeight=this.preScaledHeight=this.height=this.canvas.height;this.hiDPIAdjustments();if(!this.hasId()){this.assignId();} +if(this.image!=null){this.context.drawImage(this.image,0,0,this.image.width,this.image.height,0,0,this.preScaledWidth,this.preScaledHeight);} +this.imageData=this.context.getImageData(0,0,this.canvas.width,this.canvas.height);this.pixelData=this.imageData.data;if(Caman.allowRevert){this.initializedPixelData=new Uint8Array(this.pixelData.length);this.originalPixelData=new Uint8Array(this.pixelData.length);_ref=this.pixelData;for(i=_i=0,_len=_ref.length;_i<_len;i=++_i){pixel=_ref[i];this.initializedPixelData[i]=pixel;this.originalPixelData[i]=pixel;}} +this.dimensions={width:this.canvas.width,height:this.canvas.height};Store.put(this.id,this);this.callback.call(this,this);return this.callback=function(){};};Caman.prototype.resetOriginalPixelData=function(){var pixel,_i,_len,_ref,_results;if(!Caman.allowRevert){throw"Revert disabled";} +this.originalPixelData=new Uint8Array(this.pixelData.length);_ref=this.pixelData;_results=[];for(_i=0,_len=_ref.length;_i<_len;_i++){pixel=_ref[_i];_results.push(this.originalPixelData.push(pixel));} +return _results;};Caman.prototype.hasId=function(){return Caman.getAttrId(this.canvas)!=null;};Caman.prototype.assignId=function(){if(Caman.NodeJS||this.canvas.getAttribute('data-caman-id')){return;} +return this.canvas.setAttribute('data-caman-id',this.id);};Caman.prototype.hiDPIDisabled=function(){return this.canvas.getAttribute('data-caman-hidpi-disabled')!==null;};Caman.prototype.hiDPIAdjustments=function(){var ratio;if(Caman.NodeJS||this.hiDPIDisabled()){return;} +ratio=this.hiDPIRatio();if(ratio!==1){Log.debug("HiDPI ratio = "+ratio);this.scaled=true;this.preScaledWidth=this.canvas.width;this.preScaledHeight=this.canvas.height;this.canvas.width=this.preScaledWidth*ratio;this.canvas.height=this.preScaledHeight*ratio;this.canvas.style.width=""+this.preScaledWidth+"px";this.canvas.style.height=""+this.preScaledHeight+"px";this.context.scale(ratio,ratio);this.width=this.originalWidth=this.canvas.width;return this.height=this.originalHeight=this.canvas.height;}};Caman.prototype.hiDPIRatio=function(){var backingStoreRatio,devicePixelRatio;devicePixelRatio=window.devicePixelRatio||1;backingStoreRatio=this.context.webkitBackingStorePixelRatio||this.context.mozBackingStorePixelRatio||this.context.msBackingStorePixelRatio||this.context.oBackingStorePixelRatio||this.context.backingStorePixelRatio||1;return devicePixelRatio/backingStoreRatio;};Caman.prototype.hiDPICapable=function(){return window.devicePixelRatio!==1;};Caman.prototype.needsHiDPISwap=function(){if(this.hiDPIDisabled()||!this.hiDPICapable()){return false;} +return this.hiDPIReplacement()!==null;};Caman.prototype.hiDPIReplacement=function(){if(this.image==null){return null;} +return this.image.getAttribute('data-caman-hidpi');};Caman.prototype.replaceCanvas=function(newCanvas){var oldCanvas;oldCanvas=this.canvas;this.canvas=newCanvas;this.context=this.canvas.getContext('2d');oldCanvas.parentNode.replaceChild(this.canvas,oldCanvas);this.width=this.canvas.width;this.height=this.canvas.height;this.imageData=this.context.getImageData(0,0,this.canvas.width,this.canvas.height);this.pixelData=this.imageData.data;return this.dimensions={width:this.canvas.width,height:this.canvas.height};};Caman.prototype.render=function(callback){var _this=this;if(callback==null){callback=function(){};} +Event.trigger(this,"renderStart");return this.renderer.execute(function(){_this.context.putImageData(_this.imageData,0,0);return callback.call(_this);});};Caman.prototype.revert=function(){var i,pixel,_i,_len,_ref;if(!Caman.allowRevert){throw"Revert disabled";} +_ref=this.originalVisiblePixels();for(i=_i=0,_len=_ref.length;_i<_len;i=++_i){pixel=_ref[i];this.pixelData[i]=pixel;} +return this.context.putImageData(this.imageData,0,0);};Caman.prototype.reset=function(){var canvas,ctx,i,imageData,pixel,pixelData,_i,_len,_ref;canvas=document.createElement('canvas');Util.copyAttributes(this.canvas,canvas);canvas.width=this.originalWidth;canvas.height=this.originalHeight;ctx=canvas.getContext('2d');imageData=ctx.getImageData(0,0,canvas.width,canvas.height);pixelData=imageData.data;_ref=this.initializedPixelData;for(i=_i=0,_len=_ref.length;_i<_len;i=++_i){pixel=_ref[i];pixelData[i]=pixel;} +ctx.putImageData(imageData,0,0);this.cropCoordinates={x:0,y:0};this.resized=false;return this.replaceCanvas(canvas);};Caman.prototype.originalVisiblePixels=function(){var canvas,coord,ctx,endX,endY,i,imageData,pixel,pixelData,pixels,scaledCanvas,startX,startY,width,_i,_j,_len,_ref,_ref1,_ref2,_ref3;if(!Caman.allowRevert){throw"Revert disabled";} +pixels=[];startX=this.cropCoordinates.x;endX=startX+this.width;startY=this.cropCoordinates.y;endY=startY+this.height;if(this.resized){canvas=document.createElement('canvas');canvas.width=this.originalWidth;canvas.height=this.originalHeight;ctx=canvas.getContext('2d');imageData=ctx.getImageData(0,0,canvas.width,canvas.height);pixelData=imageData.data;_ref=this.originalPixelData;for(i=_i=0,_len=_ref.length;_i<_len;i=++_i){pixel=_ref[i];pixelData[i]=pixel;} +ctx.putImageData(imageData,0,0);scaledCanvas=document.createElement('canvas');scaledCanvas.width=this.width;scaledCanvas.height=this.height;ctx=scaledCanvas.getContext('2d');ctx.drawImage(canvas,0,0,this.originalWidth,this.originalHeight,0,0,this.width,this.height);pixelData=ctx.getImageData(0,0,this.width,this.height).data;width=this.width;}else{pixelData=this.originalPixelData;width=this.originalWidth;} +for(i=_j=0,_ref1=pixelData.length;_j<_ref1;i=_j+=4){coord=PixelInfo.locationToCoordinates(i,width);if(((startX<=(_ref2=coord.x)&&_ref2_ref;i=0<=_ref?++_i:--_i){divisor+=adjust[i];}} +this.renderer.add({type:Filter.Type.Kernel,name:name,adjust:adjust,divisor:divisor,bias:bias||0});return this;};Caman.prototype.processPlugin=function(plugin,args){this.renderer.add({type:Filter.Type.Plugin,plugin:plugin,args:args});return this;};Caman.prototype.newLayer=function(callback){var layer;layer=new Layer(this);this.canvasQueue.push(layer);this.renderer.add({type:Filter.Type.LayerDequeue});callback.call(layer);this.renderer.add({type:Filter.Type.LayerFinished});return this;};Caman.prototype.executeLayer=function(layer){return this.pushContext(layer);};Caman.prototype.pushContext=function(layer){this.layerStack.push(this.currentLayer);this.pixelStack.push(this.pixelData);this.currentLayer=layer;return this.pixelData=layer.pixelData;};Caman.prototype.popContext=function(){this.pixelData=this.pixelStack.pop();return this.currentLayer=this.layerStack.pop();};Caman.prototype.applyCurrentLayer=function(){return this.currentLayer.applyToParent();};return Caman;})();Analyze=(function(){function Analyze(c){this.c=c;} +Analyze.prototype.calculateLevels=function(){var i,levels,numPixels,_i,_j,_k,_ref;levels={r:{},g:{},b:{}};for(i=_i=0;_i<=255;i=++_i){levels.r[i]=0;levels.g[i]=0;levels.b[i]=0;} +for(i=_j=0,_ref=this.c.pixelData.length;_j<_ref;i=_j+=4){levels.r[this.c.pixelData[i]]++;levels.g[this.c.pixelData[i+1]]++;levels.b[this.c.pixelData[i+2]]++;} +numPixels=this.c.pixelData.length/4;for(i=_k=0;_k<=255;i=++_k){levels.r[i]/=numPixels;levels.g[i]/=numPixels;levels.b[i]/=numPixels;} +return levels;};return Analyze;})();Caman.DOMUpdated=function(){var img,imgs,parser,_i,_len,_results;imgs=document.querySelectorAll("img[data-caman]");if(!(imgs.length>0)){return;} +_results=[];for(_i=0,_len=imgs.length;_i<_len;_i++){img=imgs[_i];_results.push(parser=new CamanParser(img,function(){this.parse();return this.execute();}));} +return _results;};if(Caman.autoload){(function(){if(document.readyState==="complete"){return Caman.DOMUpdated();}else{return document.addEventListener("DOMContentLoaded",Caman.DOMUpdated,false);}})();} +CamanParser=(function(){var INST_REGEX;INST_REGEX="(\\w+)\\((.*?)\\)";function CamanParser(ele,ready){this.dataStr=ele.getAttribute('data-caman');this.caman=Caman(ele,ready.bind(this));} +CamanParser.prototype.parse=function(){var args,filter,func,inst,instFunc,m,r,unparsedInstructions,_i,_len,_ref,_results;this.ele=this.caman.canvas;r=new RegExp(INST_REGEX,'g');unparsedInstructions=this.dataStr.match(r);if(!(unparsedInstructions.length>0)){return;} +r=new RegExp(INST_REGEX);_results=[];for(_i=0,_len=unparsedInstructions.length;_i<_len;_i++){inst=unparsedInstructions[_i];_ref=inst.match(r),m=_ref[0],filter=_ref[1],args=_ref[2];instFunc=new Function("return function() { this."+filter+"("+args+"); };");try{func=instFunc();_results.push(func.call(this.caman));}catch(e){_results.push(Log.debug(e));}} +return _results;};CamanParser.prototype.execute=function(){var ele;ele=this.ele;return this.caman.render(function(){return ele.parentNode.replaceChild(this.toImage(),ele);});};return CamanParser;})();Caman.Blender=Blender=(function(){function Blender(){} +Blender.blenders={};Blender.register=function(name,func){return this.blenders[name]=func;};Blender.execute=function(name,rgbaLayer,rgbaParent){return this.blenders[name](rgbaLayer,rgbaParent);};return Blender;})();Caman.Calculate=Calculate=(function(){function Calculate(){} +Calculate.distance=function(x1,y1,x2,y2){return Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));};Calculate.randomRange=function(min,max,getFloat){var rand;if(getFloat==null){getFloat=false;} +rand=min+(Math.random()*(max-min));if(getFloat){return rand.toFixed(getFloat);}else{return Math.round(rand);}};Calculate.luminance=function(rgba){return(0.299*rgba.r)+(0.587*rgba.g)+(0.114*rgba.b);};Calculate.bezier=function(start,ctrl1,ctrl2,end,lowBound,highBound){var Ax,Ay,Bx,By,Cx,Cy,bezier,curveX,curveY,i,j,leftCoord,rightCoord,t,x0,x1,x2,x3,y0,y1,y2,y3,_i,_j,_k,_ref,_ref1;x0=start[0];y0=start[1];x1=ctrl1[0];y1=ctrl1[1];x2=ctrl2[0];y2=ctrl2[1];x3=end[0];y3=end[1];bezier={};Cx=parseInt(3*(x1-x0),10);Bx=3*(x2-x1)-Cx;Ax=x3-x0-Cx-Bx;Cy=3*(y1-y0);By=3*(y2-y1)-Cy;Ay=y3-y0-Cy-By;for(i=_i=0;_i<1000;i=++_i){t=i/1000;curveX=Math.round((Ax*Math.pow(t,3))+(Bx*Math.pow(t,2))+(Cx*t)+x0);curveY=Math.round((Ay*Math.pow(t,3))+(By*Math.pow(t,2))+(Cy*t)+y0);if(lowBound&&curveYhighBound){curveY=highBound;} +bezier[curveX]=curveY;} +if(bezier.length=_ref;i=0<=_ref?++_j:--_j){if(bezier[i]==null){leftCoord=[i-1,bezier[i-1]];for(j=_k=i,_ref1=end[0];i<=_ref1?_k<=_ref1:_k>=_ref1;j=i<=_ref1?++_k:--_k){if(bezier[j]!=null){rightCoord=[j,bezier[j]];break;}} +bezier[i]=leftCoord[1]+((rightCoord[1]-leftCoord[1])/(rightCoord[0]-leftCoord[0]))*(i-leftCoord[0]);}}} +if(bezier[end[0]]==null){bezier[end[0]]=bezier[end[0]-1];} +return bezier;};return Calculate;})();Convert=(function(){function Convert(){} +Convert.hexToRGB=function(hex){var b,g,r;if(hex.charAt(0)==="#"){hex=hex.substr(1);} +r=parseInt(hex.substr(0,2),16);g=parseInt(hex.substr(2,2),16);b=parseInt(hex.substr(4,2),16);return{r:r,g:g,b:b};};Convert.rgbToHSL=function(r,g,b){var d,h,l,max,min,s;if(typeof r==="object"){g=r.g;b=r.b;r=r.r;} +r/=255;g/=255;b/=255;max=Math.max(r,g,b);min=Math.min(r,g,b);l=(max+min)/2;if(max===min){h=s=0;}else{d=max-min;s=l>0.5?d/(2-max-min):d/(max+min);h=(function(){switch(max){case r:return(g-b)/d+(g1){t-=1;} +if(t<1/6){return p+(q-p)*6*t;} +if(t<1/2){return q;} +if(t<2/3){return p+(q-p)*(2/3-t)*6;} +return p;};Convert.rgbToHSV=function(r,g,b){var d,h,max,min,s,v;r/=255;g/=255;b/=255;max=Math.max(r,g,b);min=Math.min(r,g,b);v=max;d=max-min;s=max===0?0:d/max;if(max===min){h=0;}else{h=(function(){switch(max){case r:return(g-b)/d+(g0.04045){r=Math.pow((r+0.055)/1.055,2.4);}else{r/=12.92;} +if(g>0.04045){g=Math.pow((g+0.055)/1.055,2.4);}else{g/=12.92;} +if(b>0.04045){b=Math.pow((b+0.055)/1.055,2.4);}else{b/=12.92;} +x=r*0.4124+g*0.3576+b*0.1805;y=r*0.2126+g*0.7152+b*0.0722;z=r*0.0193+g*0.1192+b*0.9505;return{x:x*100,y:y*100,z:z*100};};Convert.xyzToRGB=function(x,y,z){var b,g,r;x/=100;y/=100;z/=100;r=(3.2406*x)+(-1.5372*y)+(-0.4986*z);g=(-0.9689*x)+(1.8758*y)+(0.0415*z);b=(0.0557*x)+(-0.2040*y)+(1.0570*z);if(r>0.0031308){r=(1.055*Math.pow(r,0.4166666667))-0.055;}else{r*=12.92;} +if(g>0.0031308){g=(1.055*Math.pow(g,0.4166666667))-0.055;}else{g*=12.92;} +if(b>0.0031308){b=(1.055*Math.pow(b,0.4166666667))-0.055;}else{b*=12.92;} +return{r:r*255,g:g*255,b:b*255};};Convert.xyzToLab=function(x,y,z){var a,b,l,whiteX,whiteY,whiteZ;if(typeof x==="object"){y=x.y;z=x.z;x=x.x;} +whiteX=95.047;whiteY=100.0;whiteZ=108.883;x/=whiteX;y/=whiteY;z/=whiteZ;if(x>0.008856451679){x=Math.pow(x,0.3333333333);}else{x=(7.787037037*x)+0.1379310345;} +if(y>0.008856451679){y=Math.pow(y,0.3333333333);}else{y=(7.787037037*y)+0.1379310345;} +if(z>0.008856451679){z=Math.pow(z,0.3333333333);}else{z=(7.787037037*z)+0.1379310345;} +l=116*y-16;a=500*(x-y);b=200*(y-z);return{l:l,a:a,b:b};};Convert.labToXYZ=function(l,a,b){var x,y,z;if(typeof l==="object"){a=l.a;b=l.b;l=l.l;} +y=(l+16)/116;x=y+(a/500);z=y-(b/200);if(x>0.2068965517){x=x*x*x;}else{x=0.1284185493*(x-0.1379310345);} +if(y>0.2068965517){y=y*y*y;}else{y=0.1284185493*(y-0.1379310345);} +if(z>0.2068965517){z=z*z*z;}else{z=0.1284185493*(z-0.1379310345);} +return{x:x*95.047,y:y*100.0,z:z*108.883};};Convert.rgbToLab=function(r,g,b){var xyz;if(typeof r==="object"){g=r.g;b=r.b;r=r.r;} +xyz=this.rgbToXYZ(r,g,b);return this.xyzToLab(xyz);};Convert.labToRGB=function(l,a,b){};return Convert;})();Event=(function(){function Event(){} +Event.events={};Event.types=["processStart","processComplete","renderStart","renderFinished","blockStarted","blockFinished"];Event.trigger=function(target,type,data){var event,_i,_len,_ref,_results;if(this.events[type]&&this.events[type].length){_ref=this.events[type];_results=[];for(_i=0,_len=_ref.length;_i<_len;_i++){event=_ref[_i];if(event.target===null||target.id===event.target.id){_results.push(event.fn.call(target,data));}else{_results.push(void 0);}} +return _results;}};Event.listen=function(target,type,fn){var _fn,_type;if(typeof target==="string"){_type=target;_fn=type;target=null;type=_type;fn=_fn;} +if(__indexOf.call(this.types,type)<0){return false;} +if(!this.events[type]){this.events[type]=[];} +this.events[type].push({target:target,fn:fn});return true;};return Event;})();Caman.Event=Event;Caman.Filter=Filter=(function(){function Filter(){} +Filter.Type={Single:1,Kernel:2,LayerDequeue:3,LayerFinished:4,LoadOverlay:5,Plugin:6};Filter.register=function(name,filterFunc){return Caman.prototype[name]=filterFunc;};return Filter;})();Caman.IO=IO=(function(){function IO(){} +IO.domainRegex=/(?:(?:http|https):\/\/)((?:\w+)\.(?:(?:\w|\.)+))/;IO.isRemote=function(img){if(img==null){return false;} +if(this.corsEnabled(img)){return false;} +return this.isURLRemote(img.src);};IO.corsEnabled=function(img){var _ref;return(img.crossOrigin!=null)&&((_ref=img.crossOrigin.toLowerCase())==='anonymous'||_ref==='use-credentials');};IO.isURLRemote=function(url){var matches;matches=url.match(this.domainRegex);if(matches){return matches[1]!==document.domain;}else{return false;}};IO.remoteCheck=function(src){if(this.isURLRemote(src)){if(!Caman.remoteProxy.length){Log.info("Attempting to load a remote image without a configured proxy. URL: "+src);}else{if(Caman.isURLRemote(Caman.remoteProxy)){Log.info("Cannot use a remote proxy for loading images.");return;} +return""+Caman.remoteProxy+"?camanProxyUrl="+(encodeURIComponent(src));}}};IO.proxyUrl=function(src){return""+Caman.remoteProxy+"?"+Caman.proxyParam+"="+(encodeURIComponent(src));};IO.useProxy=function(lang){var langToExt;langToExt={ruby:'rb',python:'py',perl:'pl',javascript:'js'};lang=lang.toLowerCase();if(langToExt[lang]!=null){lang=langToExt[lang];} +return"proxies/caman_proxy."+lang;};return IO;})();Caman.prototype.save=function(){if(typeof exports!=="undefined"&&exports!==null){return this.nodeSave.apply(this,arguments);}else{return this.browserSave.apply(this,arguments);}};Caman.prototype.browserSave=function(type){var image;if(type==null){type="png";} +type=type.toLowerCase();image=this.toBase64(type).replace("image/"+type,"image/octet-stream");return document.location.href=image;};Caman.prototype.nodeSave=function(file,overwrite){var stats;if(overwrite==null){overwrite=true;} +try{stats=fs.statSync(file);if(stats.isFile()&&!overwrite){return false;}}catch(e){Log.debug("Creating output file "+file);} +return fs.writeFile(file,this.canvas.toBuffer(),function(){return Log.debug("Finished writing to "+file);});};Caman.prototype.toImage=function(type){var img;img=document.createElement('img');img.src=this.toBase64(type);img.width=this.dimensions.width;img.height=this.dimensions.height;if(window.devicePixelRatio){img.width/=window.devicePixelRatio;img.height/=window.devicePixelRatio;} +return img;};Caman.prototype.toBase64=function(type){if(type==null){type="png";} +type=type.toLowerCase();return this.canvas.toDataURL("image/"+type);};Layer=(function(){function Layer(c){this.c=c;this.filter=this.c;this.options={blendingMode:'normal',opacity:1.0};this.layerID=Util.uniqid.get();this.canvas=typeof exports!=="undefined"&&exports!==null?new Canvas():document.createElement('canvas');this.canvas.width=this.c.dimensions.width;this.canvas.height=this.c.dimensions.height;this.context=this.canvas.getContext('2d');this.context.createImageData(this.canvas.width,this.canvas.height);this.imageData=this.context.getImageData(0,0,this.canvas.width,this.canvas.height);this.pixelData=this.imageData.data;} +Layer.prototype.newLayer=function(cb){return this.c.newLayer.call(this.c,cb);};Layer.prototype.setBlendingMode=function(mode){this.options.blendingMode=mode;return this;};Layer.prototype.opacity=function(opacity){this.options.opacity=opacity/100;return this;};Layer.prototype.copyParent=function(){var i,parentData,_i,_ref;parentData=this.c.pixelData;for(i=_i=0,_ref=this.c.pixelData.length;_i<_ref;i=_i+=4){this.pixelData[i]=parentData[i];this.pixelData[i+1]=parentData[i+1];this.pixelData[i+2]=parentData[i+2];this.pixelData[i+3]=parentData[i+3];} +return this;};Layer.prototype.fillColor=function(){return this.c.fillColor.apply(this.c,arguments);};Layer.prototype.overlayImage=function(image){if(typeof image==="object"){image=image.src;}else if(typeof image==="string"&&image[0]==="#"){image=$(image).src;} +if(!image){return this;} +this.c.renderer.renderQueue.push({type:Filter.Type.LoadOverlay,src:image,layer:this});return this;};Layer.prototype.applyToParent=function(){var i,layerData,parentData,result,rgbaLayer,rgbaParent,_i,_ref,_results;parentData=this.c.pixelStack[this.c.pixelStack.length-1];layerData=this.c.pixelData;_results=[];for(i=_i=0,_ref=layerData.length;_i<_ref;i=_i+=4){rgbaParent={r:parentData[i],g:parentData[i+1],b:parentData[i+2],a:parentData[i+3]};rgbaLayer={r:layerData[i],g:layerData[i+1],b:layerData[i+2],a:layerData[i+3]};result=Blender.execute(this.options.blendingMode,rgbaLayer,rgbaParent);result.r=Util.clampRGB(result.r);result.g=Util.clampRGB(result.g);result.b=Util.clampRGB(result.b);if(result.a==null){result.a=rgbaLayer.a;} +parentData[i]=rgbaParent.r-((rgbaParent.r-result.r)*(this.options.opacity*(result.a/255)));parentData[i+1]=rgbaParent.g-((rgbaParent.g-result.g)*(this.options.opacity*(result.a/255)));_results.push(parentData[i+2]=rgbaParent.b-((rgbaParent.b-result.b)*(this.options.opacity*(result.a/255))));} +return _results;};return Layer;})();Logger=(function(){function Logger(){var name,_i,_len,_ref;_ref=['log','info','warn','error'];for(_i=0,_len=_ref.length;_i<_len;_i++){name=_ref[_i];this[name]=(function(name){return function(){if(!Caman.DEBUG){return;} +return console[name].apply(console,arguments);};})(name);} +this.debug=this.log;} +return Logger;})();Log=new Logger();PixelInfo=(function(){PixelInfo.coordinatesToLocation=function(x,y,width){return(y*width+x)*4;};PixelInfo.locationToCoordinates=function(loc,width){var x,y;y=Math.floor(loc/(width*4));x=(loc%(width*4))/4;return{x:x,y:y};};function PixelInfo(c){this.c=c;this.loc=0;} +PixelInfo.prototype.locationXY=function(){var x,y;y=this.c.dimensions.height-Math.floor(this.loc/(this.c.dimensions.width*4));x=(this.loc%(this.c.dimensions.width*4))/4;return{x:x,y:y};};PixelInfo.prototype.getPixelRelative=function(horiz,vert){var newLoc;newLoc=this.loc+(this.c.dimensions.width*4*(vert*-1))+(4*horiz);if(newLoc>this.c.pixelData.length||newLoc<0){return{r:0,g:0,b:0,a:0};} +return{r:this.c.pixelData[newLoc],g:this.c.pixelData[newLoc+1],b:this.c.pixelData[newLoc+2],a:this.c.pixelData[newLoc+3]};};PixelInfo.prototype.putPixelRelative=function(horiz,vert,rgba){var nowLoc;nowLoc=this.loc+(this.c.dimensions.width*4*(vert*-1))+(4*horiz);if(newLoc>this.c.pixelData.length||newLoc<0){return;} +this.c.pixelData[newLoc]=rgba.r;this.c.pixelData[newLoc+1]=rgba.g;this.c.pixelData[newLoc+2]=rgba.b;this.c.pixelData[newLoc+3]=rgba.a;return true;};PixelInfo.prototype.getPixel=function(x,y){var loc;loc=this.coordinatesToLocation(x,y,this.width);return{r:this.c.pixelData[loc],g:this.c.pixelData[loc+1],b:this.c.pixelData[loc+2],a:this.c.pixelData[loc+3]};};PixelInfo.prototype.putPixel=function(x,y,rgba){var loc;loc=this.coordinatesToLocation(x,y,this.width);this.c.pixelData[loc]=rgba.r;this.c.pixelData[loc+1]=rgba.g;this.c.pixelData[loc+2]=rgba.b;return this.c.pixelData[loc+3]=rgba.a;};return PixelInfo;})();Plugin=(function(){function Plugin(){} +Plugin.plugins={};Plugin.register=function(name,plugin){return this.plugins[name]=plugin;};Plugin.execute=function(context,name,args){return this.plugins[name].apply(context,args);};return Plugin;})();Caman.Plugin=Plugin;Caman.Renderer=Renderer=(function(){Renderer.Blocks=Caman.NodeJS?require('os').cpus().length:4;function Renderer(c){var _this=this;this.c=c;this.processNext=function(){return Renderer.prototype.processNext.apply(_this,arguments);};this.renderQueue=[];this.modPixelData=null;} +Renderer.prototype.add=function(job){if(job==null){return;} +return this.renderQueue.push(job);};Renderer.prototype.processNext=function(){var layer;if(this.renderQueue.length===0){Event.trigger(this,"renderFinished");if(this.finishedFn!=null){this.finishedFn.call(this.c);} +return this;} +this.currentJob=this.renderQueue.shift();switch(this.currentJob.type){case Filter.Type.LayerDequeue:layer=this.c.canvasQueue.shift();this.c.executeLayer(layer);return this.processNext();case Filter.Type.LayerFinished:this.c.applyCurrentLayer();this.c.popContext();return this.processNext();case Filter.Type.LoadOverlay:return this.loadOverlay(this.currentJob.layer,this.currentJob.src);case Filter.Type.Plugin:return this.executePlugin();default:return this.executeFilter();}};Renderer.prototype.execute=function(callback){this.finishedFn=callback;this.modPixelData=new Uint8Array(this.c.pixelData.length);return this.processNext();};Renderer.prototype.eachBlock=function(fn){var blockN,blockPixelLength,bnum,end,f,i,lastBlockN,n,start,_i,_ref,_results,_this=this;this.blocksDone=0;n=this.c.pixelData.length;blockPixelLength=Math.floor((n/4)/Renderer.Blocks);blockN=blockPixelLength*4;lastBlockN=blockN+((n/4)%Renderer.Blocks)*4;_results=[];for(i=_i=0,_ref=Renderer.Blocks;0<=_ref?_i<_ref:_i>_ref;i=0<=_ref?++_i:--_i){start=i*blockN;end=start+(i===Renderer.Blocks-1?lastBlockN:blockN);if(Caman.NodeJS){f=Fiber(function(){return fn.call(_this,i,start,end);});bnum=f.run();_results.push(this.blockFinished(bnum));}else{_results.push(setTimeout((function(i,start,end){return function(){return fn.call(_this,i,start,end);};})(i,start,end),0));}} +return _results;};Renderer.prototype.executeFilter=function(){Event.trigger(this.c,"processStart",this.currentJob);if(this.currentJob.type===Filter.Type.Single){return this.eachBlock(this.renderBlock);}else{return this.eachBlock(this.renderKernel);}};Renderer.prototype.executePlugin=function(){Log.debug("Executing plugin "+this.currentJob.plugin);Plugin.execute(this.c,this.currentJob.plugin,this.currentJob.args);Log.debug("Plugin "+this.currentJob.plugin+" finished!");return this.processNext();};Renderer.prototype.renderBlock=function(bnum,start,end){var data,i,pixelInfo,res,_i;Log.debug("Block #"+bnum+" - Filter: "+this.currentJob.name+", Start: "+start+", End: "+end);Event.trigger(this.c,"blockStarted",{blockNum:bnum,totalBlocks:Renderer.Blocks,startPixel:start,endPixel:end});data={r:0,g:0,b:0,a:0};pixelInfo=new PixelInfo(this.c);for(i=_i=start;_i=builder;j=-builder<=builder?++_j:--_j){for(k=_k=builder;builder<=-builder?_k<=-builder:_k>=-builder;k=builder<=-builder?++_k:--_k){pixel=pixelInfo.getPixelRelative(j,k);kernel[builderIndex*3]=pixel.r;kernel[builderIndex*3+1]=pixel.g;kernel[builderIndex*3+2]=pixel.b;builderIndex++;}} +res=this.processKernel(adjust,kernel,divisor,bias);this.modPixelData[i]=Util.clampRGB(res.r);this.modPixelData[i+1]=Util.clampRGB(res.g);this.modPixelData[i+2]=Util.clampRGB(res.b);this.modPixelData[i+3]=this.c.pixelData[i+3];} +if(Caman.NodeJS){return Fiber["yield"](bnum);}else{return this.blockFinished(bnum);}};Renderer.prototype.blockFinished=function(bnum){var i,_i,_ref;if(bnum>=0){Log.debug("Block #"+bnum+" finished! Filter: "+this.currentJob.name);} +this.blocksDone++;Event.trigger(this.c,"blockFinished",{blockNum:bnum,blocksFinished:this.blocksDone,totalBlocks:Renderer.Blocks});if(this.blocksDone===Renderer.Blocks){if(this.currentJob.type===Filter.Type.Kernel){for(i=_i=0,_ref=this.c.pixelData.length;0<=_ref?_i<_ref:_i>_ref;i=0<=_ref?++_i:--_i){this.c.pixelData[i]=this.modPixelData[i];}} +if(bnum>=0){Log.debug("Filter "+this.currentJob.name+" finished!");} +Event.trigger(this.c,"processComplete",this.currentJob);return this.processNext();}};Renderer.prototype.processKernel=function(adjust,kernel,divisor,bias){var i,val,_i,_ref;val={r:0,g:0,b:0};for(i=_i=0,_ref=adjust.length;0<=_ref?_i<_ref:_i>_ref;i=0<=_ref?++_i:--_i){val.r+=adjust[i]*kernel[i*3];val.g+=adjust[i]*kernel[i*3+1];val.b+=adjust[i]*kernel[i*3+2];} +val.r=(val.r/divisor)+bias;val.g=(val.g/divisor)+bias;val.b=(val.b/divisor)+bias;return val;};Renderer.prototype.loadOverlay=function(layer,src){var img,proxyUrl,_this=this;img=document.createElement('img');img.onload=function(){layer.context.drawImage(img,0,0,_this.c.dimensions.width,_this.c.dimensions.height);layer.imageData=layer.context.getImageData(0,0,_this.c.dimensions.width,_this.c.dimensions.height);layer.pixelData=layer.imageData.data;_this.c.pixelData=layer.pixelData;return _this.processNext();};proxyUrl=IO.remoteCheck(src);return img.src=proxyUrl!=null?proxyUrl:src;};return Renderer;})();Caman.Store=Store=(function(){function Store(){} +Store.items={};Store.has=function(search){return this.items[search]!=null;};Store.get=function(search){return this.items[search];};Store.put=function(name,obj){return this.items[name]=obj;};Store.execute=function(search,callback){var _this=this;setTimeout(function(){return callback.call(_this.get(search),_this.get(search));},0);return this.get(search);};Store.flush=function(name){if(name==null){name=false;} +if(name){return delete this.items[name];}else{return this.items={};}};return Store;})();Blender.register("normal",function(rgbaLayer,rgbaParent){return{r:rgbaLayer.r,g:rgbaLayer.g,b:rgbaLayer.b};});Blender.register("multiply",function(rgbaLayer,rgbaParent){return{r:(rgbaLayer.r*rgbaParent.r)/255,g:(rgbaLayer.g*rgbaParent.g)/255,b:(rgbaLayer.b*rgbaParent.b)/255};});Blender.register("screen",function(rgbaLayer,rgbaParent){return{r:255-(((255-rgbaLayer.r)*(255-rgbaParent.r))/255),g:255-(((255-rgbaLayer.g)*(255-rgbaParent.g))/255),b:255-(((255-rgbaLayer.b)*(255-rgbaParent.b))/255)};});Blender.register("overlay",function(rgbaLayer,rgbaParent){var result;result={};result.r=rgbaParent.r>128?255-2*(255-rgbaLayer.r)*(255-rgbaParent.r)/255:(rgbaParent.r*rgbaLayer.r*2)/255;result.g=rgbaParent.g>128?255-2*(255-rgbaLayer.g)*(255-rgbaParent.g)/255:(rgbaParent.g*rgbaLayer.g*2)/255;result.b=rgbaParent.b>128?255-2*(255-rgbaLayer.b)*(255-rgbaParent.b)/255:(rgbaParent.b*rgbaLayer.b*2)/255;return result;});Blender.register("difference",function(rgbaLayer,rgbaParent){return{r:rgbaLayer.r-rgbaParent.r,g:rgbaLayer.g-rgbaParent.g,b:rgbaLayer.b-rgbaParent.b};});Blender.register("addition",function(rgbaLayer,rgbaParent){return{r:rgbaParent.r+rgbaLayer.r,g:rgbaParent.g+rgbaLayer.g,b:rgbaParent.b+rgbaLayer.b};});Blender.register("exclusion",function(rgbaLayer,rgbaParent){return{r:128-2*(rgbaParent.r-128)*(rgbaLayer.r-128)/255,g:128-2*(rgbaParent.g-128)*(rgbaLayer.g-128)/255,b:128-2*(rgbaParent.b-128)*(rgbaLayer.b-128)/255};});Blender.register("softLight",function(rgbaLayer,rgbaParent){var result;result={};result.r=rgbaParent.r>128?255-((255-rgbaParent.r)*(255-(rgbaLayer.r-128)))/255:(rgbaParent.r*(rgbaLayer.r+128))/255;result.g=rgbaParent.g>128?255-((255-rgbaParent.g)*(255-(rgbaLayer.g-128)))/255:(rgbaParent.g*(rgbaLayer.g+128))/255;result.b=rgbaParent.b>128?255-((255-rgbaParent.b)*(255-(rgbaLayer.b-128)))/255:(rgbaParent.b*(rgbaLayer.b+128))/255;return result;});Blender.register("lighten",function(rgbaLayer,rgbaParent){return{r:rgbaParent.r>rgbaLayer.r?rgbaParent.r:rgbaLayer.r,g:rgbaParent.g>rgbaLayer.g?rgbaParent.g:rgbaLayer.g,b:rgbaParent.b>rgbaLayer.b?rgbaParent.b:rgbaLayer.b};});Blender.register("darken",function(rgbaLayer,rgbaParent){return{r:rgbaParent.r>rgbaLayer.r?rgbaLayer.r:rgbaParent.r,g:rgbaParent.g>rgbaLayer.g?rgbaLayer.g:rgbaParent.g,b:rgbaParent.b>rgbaLayer.b?rgbaLayer.b:rgbaParent.b};});Filter.register("fillColor",function(){var color;if(arguments.length===1){color=Convert.hexToRGB(arguments[0]);}else{color={r:arguments[0],g:arguments[1],b:arguments[2]};} +return this.process("fillColor",function(rgba){rgba.r=color.r;rgba.g=color.g;rgba.b=color.b;rgba.a=255;return rgba;});});Filter.register("brightness",function(adjust){adjust=Math.floor(255*(adjust/100));return this.process("brightness",function(rgba){rgba.r+=adjust;rgba.g+=adjust;rgba.b+=adjust;return rgba;});});Filter.register("saturation",function(adjust){adjust*=-0.01;return this.process("saturation",function(rgba){var max;max=Math.max(rgba.r,rgba.g,rgba.b);if(rgba.r!==max){rgba.r+=(max-rgba.r)*adjust;} +if(rgba.g!==max){rgba.g+=(max-rgba.g)*adjust;} +if(rgba.b!==max){rgba.b+=(max-rgba.b)*adjust;} +return rgba;});});Filter.register("vibrance",function(adjust){adjust*=-1;return this.process("vibrance",function(rgba){var amt,avg,max;max=Math.max(rgba.r,rgba.g,rgba.b);avg=(rgba.r+rgba.g+rgba.b)/3;amt=((Math.abs(max-avg)*2/255)*adjust)/100;if(rgba.r!==max){rgba.r+=(max-rgba.r)*amt;} +if(rgba.g!==max){rgba.g+=(max-rgba.g)*amt;} +if(rgba.b!==max){rgba.b+=(max-rgba.b)*amt;} +return rgba;});});Filter.register("greyscale",function(adjust){return this.process("greyscale",function(rgba){var avg;avg=Calculate.luminance(rgba);rgba.r=avg;rgba.g=avg;rgba.b=avg;return rgba;});});Filter.register("contrast",function(adjust){adjust=Math.pow((adjust+100)/100,2);return this.process("contrast",function(rgba){rgba.r/=255;rgba.r-=0.5;rgba.r*=adjust;rgba.r+=0.5;rgba.r*=255;rgba.g/=255;rgba.g-=0.5;rgba.g*=adjust;rgba.g+=0.5;rgba.g*=255;rgba.b/=255;rgba.b-=0.5;rgba.b*=adjust;rgba.b+=0.5;rgba.b*=255;return rgba;});});Filter.register("hue",function(adjust){return this.process("hue",function(rgba){var h,hsv,rgb;hsv=Convert.rgbToHSV(rgba.r,rgba.g,rgba.b);h=hsv.h*100;h+=Math.abs(adjust);h=h%100;h/=100;hsv.h=h;rgb=Convert.hsvToRGB(hsv.h,hsv.s,hsv.v);rgb.a=rgba.a;return rgb;});});Filter.register("colorize",function(){var level,rgb;if(arguments.length===2){rgb=Convert.hexToRGB(arguments[0]);level=arguments[1];}else if(arguments.length===4){rgb={r:arguments[0],g:arguments[1],b:arguments[2]};level=arguments[3];} +return this.process("colorize",function(rgba){rgba.r-=(rgba.r-rgb.r)*(level/100);rgba.g-=(rgba.g-rgb.g)*(level/100);rgba.b-=(rgba.b-rgb.b)*(level/100);return rgba;});});Filter.register("invert",function(){return this.process("invert",function(rgba){rgba.r=255-rgba.r;rgba.g=255-rgba.g;rgba.b=255-rgba.b;return rgba;});});Filter.register("sepia",function(adjust){if(adjust==null){adjust=100;} +adjust/=100;return this.process("sepia",function(rgba){rgba.r=Math.min(255,(rgba.r*(1-(0.607*adjust)))+(rgba.g*(0.769*adjust))+(rgba.b*(0.189*adjust)));rgba.g=Math.min(255,(rgba.r*(0.349*adjust))+(rgba.g*(1-(0.314*adjust)))+(rgba.b*(0.168*adjust)));rgba.b=Math.min(255,(rgba.r*(0.272*adjust))+(rgba.g*(0.534*adjust))+(rgba.b*(1-(0.869*adjust))));return rgba;});});Filter.register("gamma",function(adjust){return this.process("gamma",function(rgba){rgba.r=Math.pow(rgba.r/255,adjust)*255;rgba.g=Math.pow(rgba.g/255,adjust)*255;rgba.b=Math.pow(rgba.b/255,adjust)*255;return rgba;});});Filter.register("noise",function(adjust){adjust=Math.abs(adjust)*2.55;return this.process("noise",function(rgba){var rand;rand=Calculate.randomRange(adjust*-1,adjust);rgba.r+=rand;rgba.g+=rand;rgba.b+=rand;return rgba;});});Filter.register("clip",function(adjust){adjust=Math.abs(adjust)*2.55;return this.process("clip",function(rgba){if(rgba.r>255-adjust){rgba.r=255;}else if(rgba.r255-adjust){rgba.g=255;}else if(rgba.g255-adjust){rgba.b=255;}else if(rgba.b0){rgba.r+=(255-rgba.r)*options.red;}else{rgba.r-=rgba.r*Math.abs(options.red);}} +if(options.green!=null){if(options.green>0){rgba.g+=(255-rgba.g)*options.green;}else{rgba.g-=rgba.g*Math.abs(options.green);}} +if(options.blue!=null){if(options.blue>0){rgba.b+=(255-rgba.b)*options.blue;}else{rgba.b-=rgba.b*Math.abs(options.blue);}} +return rgba;});});Filter.register("curves",function(){var bezier,chans,cps,ctrl1,ctrl2,end,i,start,_i,_j,_ref,_ref1;chans=arguments[0],cps=2<=arguments.length?__slice.call(arguments,1):[];if(typeof chans==="string"){chans=chans.split("");} +if(chans[0]==="v"){chans=['r','g','b'];} +if(cps.length<3||cps.length>4){throw"Invalid number of arguments to curves filter";} +start=cps[0];ctrl1=cps[1];ctrl2=cps.length===4?cps[2]:cps[1];end=cps[cps.length-1];bezier=Calculate.bezier(start,ctrl1,ctrl2,end,0,255);if(start[0]>0){for(i=_i=0,_ref=start[0];0<=_ref?_i<_ref:_i>_ref;i=0<=_ref?++_i:--_i){bezier[i]=start[1];}} +if(end[0]<255){for(i=_j=_ref1=end[0];_ref1<=255?_j<=255:_j>=255;i=_ref1<=255?++_j:--_j){bezier[i]=end[1];}} +return this.process("curves",function(rgba){var _k,_ref2;for(i=_k=0,_ref2=chans.length;0<=_ref2?_k<_ref2:_k>_ref2;i=0<=_ref2?++_k:--_k){rgba[chans[i]]=bezier[rgba[chans[i]]];} +return rgba;});});Filter.register("exposure",function(adjust){var ctrl1,ctrl2,p;p=Math.abs(adjust)/100;ctrl1=[0,255*p];ctrl2=[255-(255*p),255];if(adjust<0){ctrl1=ctrl1.reverse();ctrl2=ctrl2.reverse();} +return this.curves('rgb',[0,0],ctrl1,ctrl2,[255,255]);});Caman.Plugin.register("crop",function(width,height,x,y){var canvas,ctx;if(x==null){x=0;} +if(y==null){y=0;} +if(typeof exports!=="undefined"&&exports!==null){canvas=new Canvas(width,height);}else{canvas=document.createElement('canvas');Util.copyAttributes(this.canvas,canvas);canvas.width=width;canvas.height=height;} +ctx=canvas.getContext('2d');ctx.drawImage(this.canvas,x,y,width,height,0,0,width,height);this.cropCoordinates={x:x,y:y};this.cropped=true;return this.replaceCanvas(canvas);});Caman.Plugin.register("resize",function(newDims){var canvas,ctx;if(newDims==null){newDims=null;} +if(newDims===null||((newDims.width==null)&&(newDims.height==null))){Log.error("Invalid or missing dimensions given for resize");return;} +if(newDims.width==null){newDims.width=this.canvas.width*newDims.height/this.canvas.height;}else if(newDims.height==null){newDims.height=this.canvas.height*newDims.width/this.canvas.width;} +if(typeof exports!=="undefined"&&exports!==null){canvas=new Canvas(newDims.width,newDims.height);}else{canvas=document.createElement('canvas');Util.copyAttributes(this.canvas,canvas);canvas.width=newDims.width;canvas.height=newDims.height;} +ctx=canvas.getContext('2d');ctx.drawImage(this.canvas,0,0,this.canvas.width,this.canvas.height,0,0,newDims.width,newDims.height);this.resized=true;return this.replaceCanvas(canvas);});Caman.Filter.register("crop",function(){return this.processPlugin("crop",Array.prototype.slice.call(arguments,0));});Caman.Filter.register("resize",function(){return this.processPlugin("resize",Array.prototype.slice.call(arguments,0));});Caman.Filter.register("boxBlur",function(){return this.processKernel("Box Blur",[1,1,1,1,1,1,1,1,1]);});Caman.Filter.register("heavyRadialBlur",function(){return this.processKernel("Heavy Radial Blur",[0,0,1,0,0,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,0,0,1,0,0]);});Caman.Filter.register("gaussianBlur",function(){return this.processKernel("Gaussian Blur",[1,4,6,4,1,4,16,24,16,4,6,24,36,24,6,4,16,24,16,4,1,4,6,4,1]);});Caman.Filter.register("motionBlur",function(degrees){var kernel;if(degrees===0||degrees===180){kernel=[0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0];}else if((degrees>0&°rees<90)||(degrees>180&°rees<270)){kernel=[0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0];}else if(degrees===90||degrees===270){kernel=[0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0];}else{kernel=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1];} +return this.processKernel("Motion Blur",kernel);});Caman.Filter.register("sharpen",function(amt){if(amt==null){amt=100;} +amt/=100;return this.processKernel("Sharpen",[0,-amt,0,-amt,4*amt+1,-amt,0,-amt,0]);});vignetteFilters={brightness:function(rgba,amt,opts){rgba.r=rgba.r-(rgba.r*amt*opts.strength);rgba.g=rgba.g-(rgba.g*amt*opts.strength);rgba.b=rgba.b-(rgba.b*amt*opts.strength);return rgba;},gamma:function(rgba,amt,opts){rgba.r=Math.pow(rgba.r/255,Math.max(10*amt*opts.strength,1))*255;rgba.g=Math.pow(rgba.g/255,Math.max(10*amt*opts.strength,1))*255;rgba.b=Math.pow(rgba.b/255,Math.max(10*amt*opts.strength,1))*255;return rgba;},colorize:function(rgba,amt,opts){rgba.r-=(rgba.r-opts.color.r)*amt;rgba.g-=(rgba.g-opts.color.g)*amt;rgba.b-=(rgba.b-opts.color.b)*amt;return rgba;}};Filter.register("vignette",function(size,strength){var bezier,center,end,start;if(strength==null){strength=60;} +if(typeof size==="string"&&size.substr(-1)==="%"){if(this.dimensions.height>this.dimensions.width){size=this.dimensions.width*(parseInt(size.substr(0,size.length-1),10)/100);}else{size=this.dimensions.height*(parseInt(size.substr(0,size.length-1),10)/100);}} +strength/=100;center=[this.dimensions.width/2,this.dimensions.height/2];start=Math.sqrt(Math.pow(center[0],2)+Math.pow(center[1],2));end=start-size;bezier=Calculate.bezier([0,1],[30,30],[70,60],[100,80]);return this.process("vignette",function(rgba){var dist,div,loc;loc=this.locationXY();dist=Calculate.distance(loc.x,loc.y,center[0],center[1]);if(dist>end){div=Math.max(1,(bezier[Math.round(((dist-end)/size)*100)]/10)*strength);rgba.r=Math.pow(rgba.r/255,div)*255;rgba.g=Math.pow(rgba.g/255,div)*255;rgba.b=Math.pow(rgba.b/255,div)*255;} +return rgba;});});Filter.register("rectangularVignette",function(opts){var defaults,dim,percent,size,_i,_len,_ref;defaults={strength:50,cornerRadius:0,method:'brightness',color:{r:0,g:0,b:0}};opts=Util.extend(defaults,opts);if(!opts.size){return this;}else if(typeof opts.size==="string"){percent=parseInt(opts.size,10)/100;opts.size={width:this.dimensions.width*percent,height:this.dimensions.height*percent};}else if(typeof opts.size==="object"){_ref=["width","height"];for(_i=0,_len=_ref.length;_i<_len;_i++){dim=_ref[_i];if(typeof opts.size[dim]==="string"){opts.size[dim]=this.dimensions[dim]*(parseInt(opts.size[dim],10)/100);}}}else if(opts.size==="number"){size=opts.size;opts.size={width:size,height:size};} +if(typeof opts.cornerRadius==="string"){opts.cornerRadius=(opts.size.width/2)*(parseInt(opts.cornerRadius,10)/100);} +opts.strength/=100;opts.size.width=Math.floor(opts.size.width);opts.size.height=Math.floor(opts.size.height);opts.image={width:this.dimensions.width,height:this.dimensions.height};if(opts.method==="colorize"&&typeof opts.color==="string"){opts.color=Convert.hexToRGB(opts.color);} +opts.coords={left:(this.dimensions.width-opts.size.width)/2,right:this.dimensions.width-opts.coords.left,bottom:(this.dimensions.height-opts.size.height)/2,top:this.dimensions.height-opts.coords.bottom};opts.corners=[{x:opts.coords.left+opts.cornerRadius,y:opts.coords.top-opts.cornerRadius},{x:opts.coords.right-opts.cornerRadius,y:opts.coords.top-opts.cornerRadius},{x:opts.coords.right-opts.cornerRadius,y:opts.coords.bottom+opts.cornerRadius},{x:opts.coords.left+opts.cornerRadius,y:opts.coords.bottom+opts.cornerRadius}];opts.maxDist=Calculate.distance(0,0,opts.corners[3].x,opts.corners[3].y)-opts.cornerRadius;return this.process("rectangularVignette",function(rgba){var amt,loc,radialDist;loc=this.locationXY();if((loc.x>opts.corners[0].x&&loc.xopts.coords.bottom&&loc.yopts.coords.left&&loc.xopts.corners[3].y&&loc.yopts.corners[0].x&&loc.xopts.coords.top){amt=(loc.y-opts.coords.top)/opts.maxDist;}else if(loc.y>opts.corners[2].y&&loc.yopts.coords.right){amt=(loc.x-opts.coords.right)/opts.maxDist;}else if(loc.x>opts.corners[0].x&&loc.xopts.corners[2].y&&loc.y=opts.corners[0].y){radialDist=Caman.distance(loc.x,loc.y,opts.corners[0].x,opts.corners[0].y);amt=(radialDist-opts.cornerRadius)/opts.maxDist;}else if(loc.x>=opts.corners[1].x&&loc.y>=opts.corners[1].y){radialDist=Caman.distance(loc.x,loc.y,opts.corners[1].x,opts.corners[1].y);amt=(radialDist-opts.cornerRadius)/opts.maxDist;}else if(loc.x>=opts.corners[2].x&&loc.y<=opts.corners[2].y){radialDist=Caman.distance(loc.x,loc.y,opts.corners[2].x,opts.corners[2].y);amt=(radialDist-opts.cornerRadius)/opts.maxDist;}else if(loc.x<=opts.corners[3].x&&loc.y<=opts.corners[3].y){radialDist=Caman.distance(loc.x,loc.y,opts.corners[3].x,opts.corners[3].y);amt=(radialDist-opts.cornerRadius)/opts.maxDist;} +if(amt<0){return rgba;} +return vignetteFilters[opts.method](rgba,amt,opts);});});(function(){var BlurStack,getLinearGradientMap,getRadialGradientMap,mul_table,shg_table;mul_table=[512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,289,287,285,282,280,278,275,273,271,269,267,265,263,261,259];shg_table=[9,11,12,13,13,14,14,15,15,15,15,16,16,16,16,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24];getLinearGradientMap=function(width,height,centerX,centerY,angle,length,mirrored){var cnv,context,gradient,x1,x2,y1,y2;cnv=typeof exports!=="undefined"&&exports!==null?new Canvas():document.createElement('canvas');cnv.width=width;cnv.height=height;x1=centerX+Math.cos(angle)*length*0.5;y1=centerY+Math.sin(angle)*length*0.5;x2=centerX-Math.cos(angle)*length*0.5;y2=centerY-Math.sin(angle)*length*0.5;context=cnv.getContext("2d");gradient=context.createLinearGradient(x1,y1,x2,y2);if(!mirrored){gradient.addColorStop(0,"white");gradient.addColorStop(1,"black");}else{gradient.addColorStop(0,"white");gradient.addColorStop(0.5,"black");gradient.addColorStop(1,"white");} +context.fillStyle=gradient;context.fillRect(0,0,width,height);return context.getImageData(0,0,width,height);};getRadialGradientMap=function(width,height,centerX,centerY,radius1,radius2){var cnv,context,gradient;cnv=typeof exports!=="undefined"&&exports!==null?new Canvas():document.createElement('canvas');cnv.width=width;cnv.height=height;context=cnv.getContext("2d");gradient=context.createRadialGradient(centerX,centerY,radius1,centerX,centerY,radius2);gradient.addColorStop(1,"white");gradient.addColorStop(0,"black");context.fillStyle=gradient;context.fillRect(0,0,width,height);return context.getImageData(0,0,width,height);};BlurStack=function(){this.r=0;this.g=0;this.b=0;this.a=0;return this.next=null;};Caman.Plugin.register("compoundBlur",function(radiusData,radius,increaseFactor,blurLevels){var b_in_sum,b_out_sum,b_sum,blend,currentIndex,div,g_in_sum,g_out_sum,g_sum,height,heightMinus1,i,iblend,idx,imagePixels,index,iradius,lookupValue,mul_sum,p,pb,pg,pixels,pr,r_in_sum,r_out_sum,r_sum,radiusPixels,radiusPlus1,rbs,shg_sum,stack,stackEnd,stackIn,stackOut,stackStart,steps,sumFactor,w4,wh,wh4,width,widthMinus1,x,y,yi,yp,yw,_i,_j,_k,_l,_m,_n,_o,_p,_q,_r;width=this.dimensions.width;height=this.dimensions.height;imagePixels=this.pixelData;radiusPixels=radiusData.data;wh=width*height;wh4=wh<<2;pixels=[];for(i=_i=0;0<=wh4?_iwh4;i=0<=wh4?++_i:--_i){pixels[i]=imagePixels[i];} +currentIndex=0;steps=blurLevels;blurLevels-=1;while(steps-->=0){iradius=(radius+0.5)|0;if(iradius===0){continue;} +if(iradius>256){iradius=256;} +div=iradius+iradius+1;w4=width<<2;widthMinus1=width-1;heightMinus1=height-1;radiusPlus1=iradius+1;sumFactor=radiusPlus1*(radiusPlus1+1)/2;stackStart=new BlurStack();stackEnd=void 0;stack=stackStart;for(i=_j=1;1<=div?_jdiv;i=1<=div?++_j:--_j){stack=stack.next=new BlurStack();if(i===radiusPlus1){stackEnd=stack;}} +stack.next=stackStart;stackIn=null;stackOut=null;yw=yi=0;mul_sum=mul_table[iradius];shg_sum=shg_table[iradius];for(y=_k=0;0<=height?_kheight;y=0<=height?++_k:--_k){r_in_sum=g_in_sum=b_in_sum=r_sum=g_sum=b_sum=0;r_out_sum=radiusPlus1*(pr=pixels[yi]);g_out_sum=radiusPlus1*(pg=pixels[yi+1]);b_out_sum=radiusPlus1*(pb=pixels[yi+2]);r_sum+=sumFactor*pr;g_sum+=sumFactor*pg;b_sum+=sumFactor*pb;stack=stackStart;for(i=_l=0;0<=radiusPlus1?_lradiusPlus1;i=0<=radiusPlus1?++_l:--_l){stack.r=pr;stack.g=pg;stack.b=pb;stack=stack.next;} +for(i=_m=1;1<=radiusPlus1?_mradiusPlus1;i=1<=radiusPlus1?++_m:--_m){p=yi+((widthMinus1width;x=0<=width?++_n:--_n){pixels[yi]=(r_sum*mul_sum)>>shg_sum;pixels[yi+1]=(g_sum*mul_sum)>>shg_sum;pixels[yi+2]=(b_sum*mul_sum)>>shg_sum;r_sum-=r_out_sum;g_sum-=g_out_sum;b_sum-=b_out_sum;r_out_sum-=stackIn.r;g_out_sum-=stackIn.g;b_out_sum-=stackIn.b;p=(yw+((p=x+radiusPlus1)width;x=0<=width?++_o:--_o){g_in_sum=b_in_sum=r_in_sum=g_sum=b_sum=r_sum=0;yi=x<<2;r_out_sum=radiusPlus1*(pr=pixels[yi]);g_out_sum=radiusPlus1*(pg=pixels[yi+1]);b_out_sum=radiusPlus1*(pb=pixels[yi+2]);r_sum+=sumFactor*pr;g_sum+=sumFactor*pg;b_sum+=sumFactor*pb;stack=stackStart;for(i=_p=0;0<=radiusPlus1?_pradiusPlus1;i=0<=radiusPlus1?++_p:--_p){stack.r=pr;stack.g=pg;stack.b=pb;stack=stack.next;} +yp=width;for(i=_q=1;1<=radiusPlus1?_qradiusPlus1;i=1<=radiusPlus1?++_q:--_q){yi=(yp+x)<<2;r_sum+=(stack.r=(pr=pixels[yi]))*(rbs=radiusPlus1-i);g_sum+=(stack.g=(pg=pixels[yi+1]))*rbs;b_sum+=(stack.b=(pb=pixels[yi+2]))*rbs;r_in_sum+=pr;g_in_sum+=pg;b_in_sum+=pb;stack=stack.next;if(iheight;y=0<=height?++_r:--_r){p=yi<<2;pixels[p]=(r_sum*mul_sum)>>shg_sum;pixels[p+1]=(g_sum*mul_sum)>>shg_sum;pixels[p+2]=(b_sum*mul_sum)>>shg_sum;r_sum-=r_out_sum;g_sum-=g_out_sum;b_sum-=b_out_sum;r_out_sum-=stackIn.r;g_out_sum-=stackIn.g;b_out_sum-=stackIn.b;p=(x+(((p=y+radiusPlus1)-1){idx=i<<2;lookupValue=(radiusPixels[idx+2]&0xff)/255.0*blurLevels;index=lookupValue|0;if(index===currentIndex){blend=256.0*(lookupValue-(lookupValue|0));iblend=256-blend;imagePixels[idx]=(imagePixels[idx]*iblend+pixels[idx]*blend)>>8;imagePixels[idx+1]=(imagePixels[idx+1]*iblend+pixels[idx+1]*blend)>>8;imagePixels[idx+2]=(imagePixels[idx+2]*iblend+pixels[idx+2]*blend)>>8;}else if(index===currentIndex+1){imagePixels[idx]=pixels[idx];imagePixels[idx+1]=pixels[idx+1];imagePixels[idx+2]=pixels[idx+2];}} +currentIndex++;} +return this;});Caman.Filter.register("tiltShift",function(opts){var defaults,gradient;defaults={center:{x:this.dimensions.width/2,y:this.dimensions.height/2},angle:45,focusWidth:200,startRadius:3,radiusFactor:1.5,steps:3};opts=Util.extend(defaults,opts);opts.angle*=Math.PI/180;gradient=getLinearGradientMap(this.dimensions.width,this.dimensions.height,opts.center.x,opts.center.y,opts.angle,opts.focusWidth,true);return this.processPlugin("compoundBlur",[gradient,opts.startRadius,opts.radiusFactor,opts.steps]);});return Caman.Filter.register("radialBlur",function(opts){var defaults,gradient,radius1,radius2;defaults={size:50,center:{x:this.dimensions.width/2,y:this.dimensions.height/2},startRadius:3,radiusFactor:1.5,steps:3,radius:null};opts=Util.extend(defaults,opts);if(!opts.radius){opts.radius=this.dimensions.widthdiv;i=1<=div?++_i:--_i){stack=stack.next=new BlurStack();if(i===radiusPlus1){stackEnd=stack;}} +stack.next=stackStart;stackIn=null;stackOut=null;yw=yi=0;mul_sum=mul_table[radius];shg_sum=shg_table[radius];for(y=_j=0;0<=height?_jheight;y=0<=height?++_j:--_j){r_in_sum=g_in_sum=b_in_sum=r_sum=g_sum=b_sum=0;r_out_sum=radiusPlus1*(pr=pixels[yi]);g_out_sum=radiusPlus1*(pg=pixels[yi+1]);b_out_sum=radiusPlus1*(pb=pixels[yi+2]);r_sum+=sumFactor*pr;g_sum+=sumFactor*pg;b_sum+=sumFactor*pb;stack=stackStart;for(i=_k=0;0<=radiusPlus1?_kradiusPlus1;i=0<=radiusPlus1?++_k:--_k){stack.r=pr;stack.g=pg;stack.b=pb;stack=stack.next;} +for(i=_l=1;1<=radiusPlus1?_lradiusPlus1;i=1<=radiusPlus1?++_l:--_l){p=yi+((widthMinus1width;x=0<=width?++_m:--_m){pixels[yi]=(r_sum*mul_sum)>>shg_sum;pixels[yi+1]=(g_sum*mul_sum)>>shg_sum;pixels[yi+2]=(b_sum*mul_sum)>>shg_sum;r_sum-=r_out_sum;g_sum-=g_out_sum;b_sum-=b_out_sum;r_out_sum-=stackIn.r;g_out_sum-=stackIn.g;b_out_sum-=stackIn.b;p=(yw+((p=x+radius+1)width;x=0<=width?++_n:--_n){g_in_sum=b_in_sum=r_in_sum=g_sum=b_sum=r_sum=0;yi=x<<2;r_out_sum=radiusPlus1*(pr=pixels[yi]);g_out_sum=radiusPlus1*(pg=pixels[yi+1]);b_out_sum=radiusPlus1*(pb=pixels[yi+2]);r_sum+=sumFactor*pr;g_sum+=sumFactor*pg;b_sum+=sumFactor*pb;stack=stackStart;for(i=_o=0;0<=radiusPlus1?_oradiusPlus1;i=0<=radiusPlus1?++_o:--_o){stack.r=pr;stack.g=pg;stack.b=pb;stack=stack.next;} +yp=width;for(i=_p=1;1<=radius?_p<=radius:_p>=radius;i=1<=radius?++_p:--_p){yi=(yp+x)<<2;r_sum+=(stack.r=(pr=pixels[yi]))*(rbs=radiusPlus1-i);g_sum+=(stack.g=(pg=pixels[yi+1]))*rbs;b_sum+=(stack.b=(pb=pixels[yi+2]))*rbs;r_in_sum+=pr;g_in_sum+=pg;b_in_sum+=pb;stack=stack.next;if(iheight;y=0<=height?++_q:--_q){p=yi<<2;pixels[p]=(r_sum*mul_sum)>>shg_sum;pixels[p+1]=(g_sum*mul_sum)>>shg_sum;pixels[p+2]=(b_sum*mul_sum)>>shg_sum;r_sum-=r_out_sum;g_sum-=g_out_sum;b_sum-=b_out_sum;r_out_sum-=stackIn.r;g_out_sum-=stackIn.g;b_out_sum-=stackIn.b;p=(x+(((p=y+radiusPlus1) + * http://github.com/tapmodo/Jcrop + * Copyright (c) 2008-2013 Tapmodo Interactive LLC {{{ + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * }}} + */ + +(function ($) { + + $.Jcrop = function (obj, opt) { + var options = $.extend({}, $.Jcrop.defaults), + docOffset, + _ua = navigator.userAgent.toLowerCase(), + is_msie = /msie/.test(_ua), + ie6mode = /msie [1-6]\./.test(_ua); + + // Internal Methods {{{ + function px(n) { + return Math.round(n) + 'px'; + } + function cssClass(cl) { + return options.baseClass + '-' + cl; + } + function supportsColorFade() { + return $.fx.step.hasOwnProperty('backgroundColor'); + } + function getPos(obj) //{{{ + { + var pos = $(obj).offset(); + return [pos.left, pos.top]; + } + //}}} + function mouseAbs(e) //{{{ + { + return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])]; + } + //}}} + function setOptions(opt) //{{{ + { + if (typeof (opt) !== 'object') opt = {}; + options = $.extend(options, opt); + + $.each(['onChange', 'onSelect', 'onRelease', 'onDblClick'], function (i, e) { + if (typeof (options[e]) !== 'function') options[e] = function () { }; + }); + } + //}}} + function startDragMode(mode, pos, touch) //{{{ + { + docOffset = getPos($img); + Tracker.setCursor(mode === 'move' ? mode : mode + '-resize'); + + if (mode === 'move') { + return Tracker.activateHandlers(createMover(pos), doneSelect, touch); + } + + var fc = Coords.getFixed(); + var opp = oppLockCorner(mode); + var opc = Coords.getCorner(oppLockCorner(opp)); + + Coords.setPressed(Coords.getCorner(opp)); + Coords.setCurrent(opc); + + Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect, touch); + } + //}}} + function dragmodeHandler(mode, f) //{{{ + { + return function (pos) { + if (!options.aspectRatio) { + switch (mode) { + case 'e': + pos[1] = f.y2; + break; + case 'w': + pos[1] = f.y2; + break; + case 'n': + pos[0] = f.x2; + break; + case 's': + pos[0] = f.x2; + break; + } + } else { + switch (mode) { + case 'e': + pos[1] = f.y + 1; + break; + case 'w': + pos[1] = f.y + 1; + break; + case 'n': + pos[0] = f.x + 1; + break; + case 's': + pos[0] = f.x + 1; + break; + } + } + Coords.setCurrent(pos); + Selection.update(); + }; + } + //}}} + function createMover(pos) //{{{ + { + var lloc = pos; + KeyManager.watchKeys(); + + return function (pos) { + Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]); + lloc = pos; + + Selection.update(); + }; + } + //}}} + function oppLockCorner(ord) //{{{ + { + switch (ord) { + case 'n': + return 'sw'; + case 's': + return 'nw'; + case 'e': + return 'nw'; + case 'w': + return 'ne'; + case 'ne': + return 'sw'; + case 'nw': + return 'se'; + case 'se': + return 'nw'; + case 'sw': + return 'ne'; + } + } + //}}} + function createDragger(ord) //{{{ + { + return function (e) { + if (options.disabled) { + return false; + } + if ((ord === 'move') && !options.allowMove) { + return false; + } + + // Fix position of crop area when dragged the very first time. + // Necessary when crop image is in a hidden element when page is loaded. + docOffset = getPos($img); + + btndown = true; + startDragMode(ord, mouseAbs(e)); + e.stopPropagation(); + e.preventDefault(); + return false; + }; + } + //}}} + function presize($obj, w, h) //{{{ + { + var nw = $obj.width(), + nh = $obj.height(); + if ((nw > w) && w > 0) { + nw = w; + nh = (w / $obj.width()) * $obj.height(); + } + if ((nh > h) && h > 0) { + nh = h; + nw = (h / $obj.height()) * $obj.width(); + } + xscale = $obj.width() / nw; + yscale = $obj.height() / nh; + $obj.width(nw).height(nh); + } + //}}} + function unscale(c) //{{{ + { + return { + x: c.x * xscale, + y: c.y * yscale, + x2: c.x2 * xscale, + y2: c.y2 * yscale, + w: c.w * xscale, + h: c.h * yscale + }; + } + //}}} + function doneSelect(pos) //{{{ + { + var c = Coords.getFixed(); + if ((c.w > options.minSelect[0]) && (c.h > options.minSelect[1])) { + Selection.enableHandles(); + Selection.done(); + } else { + Selection.release(); + } + Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); + } + //}}} + function newSelection(e) //{{{ + { + if (options.disabled) { + return false; + } + if (!options.allowSelect) { + return false; + } + btndown = true; + docOffset = getPos($img); + Selection.disableHandles(); + Tracker.setCursor('crosshair'); + var pos = mouseAbs(e); + Coords.setPressed(pos); + Selection.update(); + Tracker.activateHandlers(selectDrag, doneSelect, e.type.substring(0, 5) === 'touch'); + KeyManager.watchKeys(); + + e.stopPropagation(); + e.preventDefault(); + return false; + } + //}}} + function selectDrag(pos) //{{{ + { + Coords.setCurrent(pos); + Selection.update(); + } + //}}} + function newTracker() //{{{ + { + var trk = $('
').addClass(cssClass('tracker')); + if (is_msie) { + trk.css({ + opacity: 0, + backgroundColor: 'white' + }); + } + return trk; + } + //}}} + + // }}} + // Initialization {{{ + // Sanitize some options {{{ + if (typeof (obj) !== 'object') { + obj = $(obj)[0]; + } + if (typeof (opt) !== 'object') { + opt = {}; + } + // }}} + setOptions(opt); + // Initialize some jQuery objects {{{ + // The values are SET on the image(s) for the interface + // If the original image has any of these set, they will be reset + // However, if you destroy() the Jcrop instance the original image's + // character in the DOM will be as you left it. + var img_css = { + border: 'none', + visibility: 'visible', + margin: 0, + padding: 0, + position: 'absolute', + top: 0, + left: 0 + }; + + var $origimg = $(obj), + img_mode = true; + + if (obj.tagName == 'IMG') { + // Fix size of crop image. + // Necessary when crop image is within a hidden element when page is loaded. + if ($origimg[0].width != 0 && $origimg[0].height != 0) { + // Obtain dimensions from contained img element. + $origimg.width($origimg[0].width); + $origimg.height($origimg[0].height); + } else { + // Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0). + var tempImage = new Image(); + tempImage.src = $origimg[0].src; + $origimg.width(tempImage.width); + $origimg.height(tempImage.height); + } + + var $img = $origimg.clone().removeAttr('id').css(img_css).show(); + + $img.width($origimg.width()); + $img.height($origimg.height()); + $origimg.after($img).hide(); + + } else { + $img = $origimg.css(img_css).show(); + img_mode = false; + if (options.shade === null) { options.shade = true; } + } + + presize($img, options.boxWidth, options.boxHeight); + + var boundx = $img.width(), + boundy = $img.height(), + + + $div = $('
').width(boundx).height(boundy).addClass(cssClass('holder')).css({ + position: 'relative', + backgroundColor: options.bgColor + }).insertAfter($origimg).append($img); + + if (options.addClass) { + $div.addClass(options.addClass); + } + + var $img2 = $('
'), + + $img_holder = $('
') + .width('100%').height('100%').css({ + zIndex: 310, + position: 'absolute', + overflow: 'hidden' + }), + + $hdl_holder = $('
') + .width('100%').height('100%').css('zIndex', 320), + + $sel = $('
') + .css({ + position: 'absolute', + zIndex: 600 + }).dblclick(function () { + var c = Coords.getFixed(); + options.onDblClick.call(api, c); + }).insertBefore($img).append($img_holder, $hdl_holder); + + if (img_mode) { + + $img2 = $('') + .attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy), + + $img_holder.append($img2); + + } + + if (ie6mode) { + $sel.css({ + overflowY: 'hidden' + }); + } + + var bound = options.boundary; + var $trk = newTracker().width(boundx + (bound * 2)).height(boundy + (bound * 2)).css({ + position: 'absolute', + top: px(-bound), + left: px(-bound), + zIndex: 290 + }).mousedown(newSelection); + + /* }}} */ + // Set more variables {{{ + var bgcolor = options.bgColor, + bgopacity = options.bgOpacity, + xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true, + btndown, animating, shift_down; + + docOffset = getPos($img); + // }}} + // }}} + // Internal Modules {{{ + // Touch Module {{{ + var Touch = (function () { + // Touch support detection function adapted (under MIT License) + // from code by Jeffrey Sambells - http://github.com/iamamused/ + function hasTouchSupport() { + var support = {}, events = ['touchstart', 'touchmove', 'touchend'], + el = document.createElement('div'), i; + + try { + for (i = 0; i < events.length; i++) { + var eventName = events[i]; + eventName = 'on' + eventName; + var isSupported = (eventName in el); + if (!isSupported) { + el.setAttribute(eventName, 'return;'); + isSupported = typeof el[eventName] == 'function'; + } + support[events[i]] = isSupported; + } + return support.touchstart && support.touchend && support.touchmove; + } + catch (err) { + return false; + } + } + + function detectSupport() { + if ((options.touchSupport === true) || (options.touchSupport === false)) return options.touchSupport; + else return hasTouchSupport(); + } + return { + createDragger: function (ord) { + return function (e) { + if (options.disabled) { + return false; + } + if ((ord === 'move') && !options.allowMove) { + return false; + } + docOffset = getPos($img); + btndown = true; + startDragMode(ord, mouseAbs(Touch.cfilter(e)), true); + e.stopPropagation(); + e.preventDefault(); + return false; + }; + }, + newSelection: function (e) { + return newSelection(Touch.cfilter(e)); + }, + cfilter: function (e) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + return e; + }, + isSupported: hasTouchSupport, + support: detectSupport() + }; + }()); + // }}} + // Coords Module {{{ + var Coords = (function () { + var x1 = 0, + y1 = 0, + x2 = 0, + y2 = 0, + ox, oy; + + function setPressed(pos) //{{{ + { + pos = rebound(pos); + x2 = x1 = pos[0]; + y2 = y1 = pos[1]; + } + //}}} + function setCurrent(pos) //{{{ + { + pos = rebound(pos); + ox = pos[0] - x2; + oy = pos[1] - y2; + x2 = pos[0]; + y2 = pos[1]; + } + //}}} + function getOffset() //{{{ + { + return [ox, oy]; + } + //}}} + function moveOffset(offset) //{{{ + { + var ox = offset[0], + oy = offset[1]; + + if (0 > x1 + ox) { + ox -= ox + x1; + } + if (0 > y1 + oy) { + oy -= oy + y1; + } + + if (boundy < y2 + oy) { + oy += boundy - (y2 + oy); + } + if (boundx < x2 + ox) { + ox += boundx - (x2 + ox); + } + + x1 += ox; + x2 += ox; + y1 += oy; + y2 += oy; + } + //}}} + function getCorner(ord) //{{{ + { + var c = getFixed(); + switch (ord) { + case 'ne': + return [c.x2, c.y]; + case 'nw': + return [c.x, c.y]; + case 'se': + return [c.x2, c.y2]; + case 'sw': + return [c.x, c.y2]; + } + } + //}}} + function getFixed() //{{{ + { + if (!options.aspectRatio) { + return getRect(); + } + // This function could use some optimization I think... + var aspect = options.aspectRatio, + min_x = options.minSize[0] / xscale, + + + //min_y = options.minSize[1]/yscale, + max_x = options.maxSize[0] / xscale, + max_y = options.maxSize[1] / yscale, + rw = x2 - x1, + rh = y2 - y1, + rwa = Math.abs(rw), + rha = Math.abs(rh), + real_ratio = rwa / rha, + xx, yy, w, h; + + if (max_x === 0) { + max_x = boundx * 10; + } + if (max_y === 0) { + max_y = boundy * 10; + } + if (real_ratio < aspect) { + yy = y2; + w = rha * aspect; + xx = rw < 0 ? x1 - w : w + x1; + + if (xx < 0) { + xx = 0; + h = Math.abs((xx - x1) / aspect); + yy = rh < 0 ? y1 - h : h + y1; + } else if (xx > boundx) { + xx = boundx; + h = Math.abs((xx - x1) / aspect); + yy = rh < 0 ? y1 - h : h + y1; + } + } else { + xx = x2; + h = rwa / aspect; + yy = rh < 0 ? y1 - h : y1 + h; + if (yy < 0) { + yy = 0; + w = Math.abs((yy - y1) * aspect); + xx = rw < 0 ? x1 - w : w + x1; + } else if (yy > boundy) { + yy = boundy; + w = Math.abs(yy - y1) * aspect; + xx = rw < 0 ? x1 - w : w + x1; + } + } + + // Magic %-) + if (xx > x1) { // right side + if (xx - x1 < min_x) { + xx = x1 + min_x; + } else if (xx - x1 > max_x) { + xx = x1 + max_x; + } + if (yy > y1) { + yy = y1 + (xx - x1) / aspect; + } else { + yy = y1 - (xx - x1) / aspect; + } + } else if (xx < x1) { // left side + if (x1 - xx < min_x) { + xx = x1 - min_x; + } else if (x1 - xx > max_x) { + xx = x1 - max_x; + } + if (yy > y1) { + yy = y1 + (x1 - xx) / aspect; + } else { + yy = y1 - (x1 - xx) / aspect; + } + } + + if (xx < 0) { + x1 -= xx; + xx = 0; + } else if (xx > boundx) { + x1 -= xx - boundx; + xx = boundx; + } + + if (yy < 0) { + y1 -= yy; + yy = 0; + } else if (yy > boundy) { + y1 -= yy - boundy; + yy = boundy; + } + + return makeObj(flipCoords(x1, y1, xx, yy)); + } + //}}} + function rebound(p) //{{{ + { + if (p[0] < 0) p[0] = 0; + if (p[1] < 0) p[1] = 0; + + if (p[0] > boundx) p[0] = boundx; + if (p[1] > boundy) p[1] = boundy; + + return [Math.round(p[0]), Math.round(p[1])]; + } + //}}} + function flipCoords(x1, y1, x2, y2) //{{{ + { + var xa = x1, + xb = x2, + ya = y1, + yb = y2; + if (x2 < x1) { + xa = x2; + xb = x1; + } + if (y2 < y1) { + ya = y2; + yb = y1; + } + return [xa, ya, xb, yb]; + } + //}}} + function getRect() //{{{ + { + var xsize = x2 - x1, + ysize = y2 - y1, + delta; + + if (xlimit && (Math.abs(xsize) > xlimit)) { + x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit); + } + if (ylimit && (Math.abs(ysize) > ylimit)) { + y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit); + } + + if (ymin / yscale && (Math.abs(ysize) < ymin / yscale)) { + y2 = (ysize > 0) ? (y1 + ymin / yscale) : (y1 - ymin / yscale); + } + if (xmin / xscale && (Math.abs(xsize) < xmin / xscale)) { + x2 = (xsize > 0) ? (x1 + xmin / xscale) : (x1 - xmin / xscale); + } + + if (x1 < 0) { + x2 -= x1; + x1 -= x1; + } + if (y1 < 0) { + y2 -= y1; + y1 -= y1; + } + if (x2 < 0) { + x1 -= x2; + x2 -= x2; + } + if (y2 < 0) { + y1 -= y2; + y2 -= y2; + } + if (x2 > boundx) { + delta = x2 - boundx; + x1 -= delta; + x2 -= delta; + } + if (y2 > boundy) { + delta = y2 - boundy; + y1 -= delta; + y2 -= delta; + } + if (x1 > boundx) { + delta = x1 - boundy; + y2 -= delta; + y1 -= delta; + } + if (y1 > boundy) { + delta = y1 - boundy; + y2 -= delta; + y1 -= delta; + } + + return makeObj(flipCoords(x1, y1, x2, y2)); + } + //}}} + function makeObj(a) //{{{ + { + return { + x: a[0], + y: a[1], + x2: a[2], + y2: a[3], + w: a[2] - a[0], + h: a[3] - a[1] + }; + } + //}}} + + return { + flipCoords: flipCoords, + setPressed: setPressed, + setCurrent: setCurrent, + getOffset: getOffset, + moveOffset: moveOffset, + getCorner: getCorner, + getFixed: getFixed + }; + }()); + + //}}} + // Shade Module {{{ + var Shade = (function () { + var enabled = false, + holder = $('
').css({ + position: 'absolute', + zIndex: 240, + opacity: 0 + }), + shades = { + top: createShade(), + left: createShade().height(boundy), + right: createShade().height(boundy), + bottom: createShade() + }; + + function resizeShades(w, h) { + shades.left.css({ height: px(h) }); + shades.right.css({ height: px(h) }); + } + function updateAuto() { + return updateShade(Coords.getFixed()); + } + function updateShade(c) { + shades.top.css({ + left: px(c.x), + width: px(c.w), + height: px(c.y) + }); + shades.bottom.css({ + top: px(c.y2), + left: px(c.x), + width: px(c.w), + height: px(boundy - c.y2) + }); + shades.right.css({ + left: px(c.x2), + width: px(boundx - c.x2) + }); + shades.left.css({ + width: px(c.x) + }); + } + function createShade() { + return $('
').css({ + position: 'absolute', + backgroundColor: options.shadeColor || options.bgColor + }).appendTo(holder); + } + function enableShade() { + if (!enabled) { + enabled = true; + holder.insertBefore($img); + updateAuto(); + Selection.setBgOpacity(1, 0, 1); + $img2.hide(); + + setBgColor(options.shadeColor || options.bgColor, 1); + if (Selection.isAwake()) { + setOpacity(options.bgOpacity, 1); + } + else setOpacity(1, 1); + } + } + function setBgColor(color, now) { + colorChangeMacro(getShades(), color, now); + } + function disableShade() { + if (enabled) { + holder.remove(); + $img2.show(); + enabled = false; + if (Selection.isAwake()) { + Selection.setBgOpacity(options.bgOpacity, 1, 1); + } else { + Selection.setBgOpacity(1, 1, 1); + Selection.disableHandles(); + } + colorChangeMacro($div, 0, 1); + } + } + function setOpacity(opacity, now) { + if (enabled) { + if (options.bgFade && !now) { + holder.animate({ + opacity: 1 - opacity + }, { + queue: false, + duration: options.fadeTime + }); + } + else holder.css({ opacity: 1 - opacity }); + } + } + function refreshAll() { + options.shade ? enableShade() : disableShade(); + if (Selection.isAwake()) setOpacity(options.bgOpacity); + } + function getShades() { + return holder.children(); + } + + return { + update: updateAuto, + updateRaw: updateShade, + getShades: getShades, + setBgColor: setBgColor, + enable: enableShade, + disable: disableShade, + resize: resizeShades, + refresh: refreshAll, + opacity: setOpacity + }; + }()); + // }}} + // Selection Module {{{ + var Selection = (function () { + var awake, + hdep = 370, + borders = {}, + handle = {}, + dragbar = {}, + seehandles = false; + + // Private Methods + function insertBorder(type) //{{{ + { + var jq = $('
').css({ + position: 'absolute', + opacity: options.borderOpacity + }).addClass(cssClass(type)); + $img_holder.append(jq); + return jq; + } + //}}} + function dragDiv(ord, zi) //{{{ + { + var jq = $('
').mousedown(createDragger(ord)).css({ + cursor: ord + '-resize', + position: 'absolute', + zIndex: zi + }).addClass('ord-' + ord); + + if (Touch.support) { + jq.bind('touchstart.jcrop', Touch.createDragger(ord)); + } + + $hdl_holder.append(jq); + return jq; + } + //}}} + function insertHandle(ord) //{{{ + { + var hs = options.handleSize, + + div = dragDiv(ord, hdep++).css({ + opacity: options.handleOpacity + }).addClass(cssClass('handle')); + + if (hs) { div.width(hs).height(hs); } + + return div; + } + //}}} + function insertDragbar(ord) //{{{ + { + return dragDiv(ord, hdep++).addClass('jcrop-dragbar'); + } + //}}} + function createDragbars(li) //{{{ + { + var i; + for (i = 0; i < li.length; i++) { + dragbar[li[i]] = insertDragbar(li[i]); + } + } + //}}} + function createBorders(li) //{{{ + { + var cl, i; + for (i = 0; i < li.length; i++) { + switch (li[i]) { + case 'n': cl = 'hline'; break; + case 's': cl = 'hline bottom'; break; + case 'e': cl = 'vline right'; break; + case 'w': cl = 'vline'; break; + } + borders[li[i]] = insertBorder(cl); + } + } + //}}} + function createHandles(li) //{{{ + { + var i; + for (i = 0; i < li.length; i++) { + handle[li[i]] = insertHandle(li[i]); + } + } + //}}} + function moveto(x, y) //{{{ + { + if (!options.shade) { + $img2.css({ + top: px(-y), + left: px(-x) + }); + } + $sel.css({ + top: px(y), + left: px(x) + }); + } + //}}} + function resize(w, h) //{{{ + { + $sel.width(Math.round(w)).height(Math.round(h)); + } + //}}} + function refresh() //{{{ + { + var c = Coords.getFixed(); + + Coords.setPressed([c.x, c.y]); + Coords.setCurrent([c.x2, c.y2]); + + updateVisible(); + } + //}}} + + // Internal Methods + function updateVisible(select) //{{{ + { + if (awake) { + return update(select); + } + } + //}}} + function update(select) //{{{ + { + var c = Coords.getFixed(); + + resize(c.w, c.h); + moveto(c.x, c.y); + if (options.shade) Shade.updateRaw(c); + + awake || show(); + + if (select) { + options.onSelect.call(api, unscale(c)); + } else { + options.onChange.call(api, unscale(c)); + } + } + //}}} + function setBgOpacity(opacity, force, now) //{{{ + { + if (!awake && !force) return; + if (options.bgFade && !now) { + $img.animate({ + opacity: opacity + }, { + queue: false, + duration: options.fadeTime + }); + } else { + $img.css('opacity', opacity); + } + } + //}}} + function show() //{{{ + { + $sel.show(); + + if (options.shade) Shade.opacity(bgopacity); + else setBgOpacity(bgopacity, true); + + awake = true; + } + //}}} + function release() //{{{ + { + disableHandles(); + $sel.hide(); + + if (options.shade) Shade.opacity(1); + else setBgOpacity(1); + + awake = false; + options.onRelease.call(api); + } + //}}} + function showHandles() //{{{ + { + if (seehandles) { + $hdl_holder.show(); + } + } + //}}} + function enableHandles() //{{{ + { + seehandles = true; + if (options.allowResize) { + $hdl_holder.show(); + return true; + } + } + //}}} + function disableHandles() //{{{ + { + seehandles = false; + $hdl_holder.hide(); + } + //}}} + function animMode(v) //{{{ + { + if (v) { + animating = true; + disableHandles(); + } else { + animating = false; + enableHandles(); + } + } + //}}} + function done() //{{{ + { + animMode(false); + refresh(); + } + //}}} + // Insert draggable elements {{{ + // Insert border divs for outline + + if (options.dragEdges && $.isArray(options.createDragbars)) + createDragbars(options.createDragbars); + + if ($.isArray(options.createHandles)) + createHandles(options.createHandles); + + if (options.drawBorders && $.isArray(options.createBorders)) + createBorders(options.createBorders); + + //}}} + + // This is a hack for iOS5 to support drag/move touch functionality + $(document).bind('touchstart.jcrop-ios', function (e) { + if ($(e.currentTarget).hasClass('jcrop-tracker')) e.stopPropagation(); + }); + + var $track = newTracker().mousedown(createDragger('move')).css({ + cursor: 'move', + position: 'absolute', + zIndex: 360 + }); + + if (Touch.support) { + $track.bind('touchstart.jcrop', Touch.createDragger('move')); + } + + $img_holder.append($track); + disableHandles(); + + return { + updateVisible: updateVisible, + update: update, + release: release, + refresh: refresh, + isAwake: function () { + return awake; + }, + setCursor: function (cursor) { + $track.css('cursor', cursor); + }, + enableHandles: enableHandles, + enableOnly: function () { + seehandles = true; + }, + showHandles: showHandles, + disableHandles: disableHandles, + animMode: animMode, + setBgOpacity: setBgOpacity, + done: done + }; + }()); + + //}}} + // Tracker Module {{{ + var Tracker = (function () { + var onMove = function () { }, + onDone = function () { }, + trackDoc = options.trackDocument; + + function toFront(touch) //{{{ + { + $trk.css({ + zIndex: 450 + }); + + if (touch) + $(document) + .bind('touchmove.jcrop', trackTouchMove) + .bind('touchend.jcrop', trackTouchEnd); + + else if (trackDoc) + $(document) + .bind('mousemove.jcrop', trackMove) + .bind('mouseup.jcrop', trackUp); + } + //}}} + function toBack() //{{{ + { + $trk.css({ + zIndex: 290 + }); + $(document).unbind('.jcrop'); + } + //}}} + function trackMove(e) //{{{ + { + onMove(mouseAbs(e)); + return false; + } + //}}} + function trackUp(e) //{{{ + { + e.preventDefault(); + e.stopPropagation(); + + if (btndown) { + btndown = false; + + onDone(mouseAbs(e)); + + if (Selection.isAwake()) { + options.onSelect.call(api, unscale(Coords.getFixed())); + } + + toBack(); + onMove = function () { }; + onDone = function () { }; + } + + return false; + } + //}}} + function activateHandlers(move, done, touch) //{{{ + { + btndown = true; + onMove = move; + onDone = done; + toFront(touch); + return false; + } + //}}} + function trackTouchMove(e) //{{{ + { + onMove(mouseAbs(Touch.cfilter(e))); + return false; + } + //}}} + function trackTouchEnd(e) //{{{ + { + return trackUp(Touch.cfilter(e)); + } + //}}} + function setCursor(t) //{{{ + { + $trk.css('cursor', t); + } + //}}} + + if (!trackDoc) { + $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp); + } + + $img.before($trk); + return { + activateHandlers: activateHandlers, + setCursor: setCursor + }; + }()); + //}}} + // KeyManager Module {{{ + var KeyManager = (function () { + var $keymgr = $('').css({ + position: 'fixed', + left: '-120px', + width: '12px' + }).addClass('jcrop-keymgr'), + + $keywrap = $('
').css({ + position: 'absolute', + overflow: 'hidden' + }).append($keymgr); + + function watchKeys() //{{{ + { + if (options.keySupport) { + $keymgr.show(); + $keymgr.focus(); + } + } + //}}} + function onBlur(e) //{{{ + { + $keymgr.hide(); + } + //}}} + function doNudge(e, x, y) //{{{ + { + if (options.allowMove) { + Coords.moveOffset([x, y]); + Selection.updateVisible(true); + } + e.preventDefault(); + e.stopPropagation(); + } + //}}} + function parseKey(e) //{{{ + { + if (e.ctrlKey || e.metaKey) { + return true; + } + shift_down = e.shiftKey ? true : false; + var nudge = shift_down ? 10 : 1; + + switch (e.keyCode) { + case 37: + doNudge(e, -nudge, 0); + break; + case 39: + doNudge(e, nudge, 0); + break; + case 38: + doNudge(e, 0, -nudge); + break; + case 40: + doNudge(e, 0, nudge); + break; + case 27: + if (options.allowSelect) Selection.release(); + break; + case 9: + return true; + } + + return false; + } + //}}} + + if (options.keySupport) { + $keymgr.keydown(parseKey).blur(onBlur); + if (ie6mode || !options.fixedSupport) { + $keymgr.css({ + position: 'absolute', + left: '-20px' + }); + $keywrap.append($keymgr).insertBefore($img); + } else { + $keymgr.insertBefore($img); + } + } + + + return { + watchKeys: watchKeys + }; + }()); + //}}} + // }}} + // API methods {{{ + function setClass(cname) //{{{ + { + $div.removeClass().addClass(cssClass('holder')).addClass(cname); + } + //}}} + function animateTo(a, callback) //{{{ + { + var x1 = a[0] / xscale, + y1 = a[1] / yscale, + x2 = a[2] / xscale, + y2 = a[3] / yscale; + + if (animating) { + return; + } + + var animto = Coords.flipCoords(x1, y1, x2, y2), + c = Coords.getFixed(), + initcr = [c.x, c.y, c.x2, c.y2], + animat = initcr, + interv = options.animationDelay, + ix1 = animto[0] - initcr[0], + iy1 = animto[1] - initcr[1], + ix2 = animto[2] - initcr[2], + iy2 = animto[3] - initcr[3], + pcent = 0, + velocity = options.swingSpeed; + + x1 = animat[0]; + y1 = animat[1]; + x2 = animat[2]; + y2 = animat[3]; + + Selection.animMode(true); + var anim_timer; + + function queueAnimator() { + window.setTimeout(animator, interv); + } + var animator = (function () { + return function () { + pcent += (100 - pcent) / velocity; + + animat[0] = Math.round(x1 + ((pcent / 100) * ix1)); + animat[1] = Math.round(y1 + ((pcent / 100) * iy1)); + animat[2] = Math.round(x2 + ((pcent / 100) * ix2)); + animat[3] = Math.round(y2 + ((pcent / 100) * iy2)); + + if (pcent >= 99.8) { + pcent = 100; + } + if (pcent < 100) { + setSelectRaw(animat); + queueAnimator(); + } else { + Selection.done(); + Selection.animMode(false); + if (typeof (callback) === 'function') { + callback.call(api); + } + } + }; + }()); + queueAnimator(); + } + //}}} + function setSelect(rect) //{{{ + { + setSelectRaw([rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale]); + options.onSelect.call(api, unscale(Coords.getFixed())); + Selection.enableHandles(); + } + //}}} + function setSelectRaw(l) //{{{ + { + Coords.setPressed([l[0], l[1]]); + Coords.setCurrent([l[2], l[3]]); + Selection.update(); + } + //}}} + function tellSelect() //{{{ + { + return unscale(Coords.getFixed()); + } + //}}} + function tellScaled() //{{{ + { + return Coords.getFixed(); + } + //}}} + function setOptionsNew(opt) //{{{ + { + setOptions(opt); + interfaceUpdate(); + } + //}}} + function disableCrop() //{{{ + { + options.disabled = true; + Selection.disableHandles(); + Selection.setCursor('default'); + Tracker.setCursor('default'); + } + //}}} + function enableCrop() //{{{ + { + options.disabled = false; + interfaceUpdate(); + } + //}}} + function cancelCrop() //{{{ + { + Selection.done(); + Tracker.activateHandlers(null, null); + } + //}}} + function destroy() //{{{ + { + $div.remove(); + $origimg.show(); + $origimg.css('visibility', 'visible'); + $(obj).removeData('Jcrop'); + } + //}}} + function setImage(src, callback) //{{{ + { + Selection.release(); + disableCrop(); + var img = new Image(); + img.onload = function () { + var iw = img.width; + var ih = img.height; + var bw = options.boxWidth; + var bh = options.boxHeight; + $img.width(iw).height(ih); + $img.attr('src', src); + $img2.attr('src', src); + presize($img, bw, bh); + boundx = $img.width(); + boundy = $img.height(); + $img2.width(boundx).height(boundy); + $trk.width(boundx + (bound * 2)).height(boundy + (bound * 2)); + $div.width(boundx).height(boundy); + Shade.resize(boundx, boundy); + enableCrop(); + + if (typeof (callback) === 'function') { + callback.call(api); + } + }; + img.src = src; + } + //}}} + function colorChangeMacro($obj, color, now) { + var mycolor = color || options.bgColor; + if (options.bgFade && supportsColorFade() && options.fadeTime && !now) { + $obj.animate({ + backgroundColor: mycolor + }, { + queue: false, + duration: options.fadeTime + }); + } else { + $obj.css('backgroundColor', mycolor); + } + } + function interfaceUpdate(alt) //{{{ + // This method tweaks the interface based on options object. + // Called when options are changed and at end of initialization. + { + if (options.allowResize) { + if (alt) { + Selection.enableOnly(); + } else { + Selection.enableHandles(); + } + } else { + Selection.disableHandles(); + } + + Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); + Selection.setCursor(options.allowMove ? 'move' : 'default'); + + if (options.hasOwnProperty('trueSize')) { + xscale = options.trueSize[0] / boundx; + yscale = options.trueSize[1] / boundy; + } + + if (options.hasOwnProperty('setSelect')) { + setSelect(options.setSelect); + Selection.done(); + delete (options.setSelect); + } + + Shade.refresh(); + + if (options.bgColor != bgcolor) { + colorChangeMacro( + options.shade ? Shade.getShades() : $div, + options.shade ? + (options.shadeColor || options.bgColor) : + options.bgColor + ); + bgcolor = options.bgColor; + } + + if (bgopacity != options.bgOpacity) { + bgopacity = options.bgOpacity; + if (options.shade) Shade.refresh(); + else Selection.setBgOpacity(bgopacity); + } + + xlimit = options.maxSize[0] || 0; + ylimit = options.maxSize[1] || 0; + xmin = options.minSize[0] || 0; + ymin = options.minSize[1] || 0; + + if (options.hasOwnProperty('outerImage')) { + $img.attr('src', options.outerImage); + delete (options.outerImage); + } + + Selection.refresh(); + } + //}}} + //}}} + + if (Touch.support) $trk.bind('touchstart.jcrop', Touch.newSelection); + + $hdl_holder.hide(); + interfaceUpdate(true); + + var api = { + setImage: setImage, + animateTo: animateTo, + setSelect: setSelect, + setOptions: setOptionsNew, + tellSelect: tellSelect, + tellScaled: tellScaled, + setClass: setClass, + + disable: disableCrop, + enable: enableCrop, + cancel: cancelCrop, + release: Selection.release, + destroy: destroy, + + focus: KeyManager.watchKeys, + + getBounds: function () { + return [boundx * xscale, boundy * yscale]; + }, + getWidgetSize: function () { + return [boundx, boundy]; + }, + getScaleFactor: function () { + return [xscale, yscale]; + }, + getOptions: function () { + // careful: internal values are returned + return options; + }, + + ui: { + holder: $div, + selection: $sel + } + }; + + if (is_msie) $div.bind('selectstart', function () { return false; }); + + $origimg.data('Jcrop', api); + return api; + }; + $.fn.Jcrop = function (options, callback) //{{{ + { + var api; + // Iterate over each object, attach Jcrop + this.each(function () { + // If we've already attached to this object + if ($(this).data('Jcrop')) { + // The API can be requested this way (undocumented) + if (options === 'api') return $(this).data('Jcrop'); + // Otherwise, we just reset the options... + else $(this).data('Jcrop').setOptions(options); + } + // If we haven't been attached, preload and attach + else { + if (this.tagName == 'IMG') + $.Jcrop.Loader(this, function () { + $(this).css({ display: 'block', visibility: 'hidden' }); + api = $.Jcrop(this, options); + if ($.isFunction(callback)) callback.call(api); + }); + else { + $(this).css({ display: 'block', visibility: 'hidden' }); + api = $.Jcrop(this, options); + if ($.isFunction(callback)) callback.call(api); + } + } + }); + + // Return "this" so the object is chainable (jQuery-style) + return this; + }; + //}}} + // $.Jcrop.Loader - basic image loader {{{ + + $.Jcrop.Loader = function (imgobj, success, error) { + var $img = $(imgobj), img = $img[0]; + + function completeCheck() { + if (img.complete) { + $img.unbind('.jcloader'); + if ($.isFunction(success)) success.call(img); + } + else window.setTimeout(completeCheck, 50); + } + + $img + .bind('load.jcloader', completeCheck) + .bind('error.jcloader', function (e) { + $img.unbind('.jcloader'); + if ($.isFunction(error)) error.call(img); + }); + + if (img.complete && $.isFunction(success)) { + $img.unbind('.jcloader'); + success.call(img); + } + }; + + //}}} + // Global Defaults {{{ + $.Jcrop.defaults = { + + // Basic Settings + allowSelect: true, + allowMove: true, + allowResize: true, + + trackDocument: true, + + // Styling Options + baseClass: 'jcrop', + addClass: null, + bgColor: 'black', + bgOpacity: 0.6, + bgFade: false, + borderOpacity: 0.4, + handleOpacity: 0.5, + handleSize: null, + + aspectRatio: 0, + keySupport: true, + createHandles: ['n', 's', 'e', 'w', 'nw', 'ne', 'se', 'sw'], + createDragbars: ['n', 's', 'e', 'w'], + createBorders: ['n', 's', 'e', 'w'], + drawBorders: true, + dragEdges: true, + fixedSupport: true, + touchSupport: null, + + shade: null, + + boxWidth: 0, + boxHeight: 0, + boundary: 2, + fadeTime: 400, + animationDelay: 20, + swingSpeed: 3, + + minSelect: [0, 0], + maxSize: [0, 0], + minSize: [0, 0], + + // Callbacks / Event Handlers + onChange: function () { }, + onSelect: function () { }, + onDblClick: function () { }, + onRelease: function () { } + }; + + // }}} +}(jQuery)); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/jcrop/js/jquery.Jcrop.min.js b/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/jcrop/js/jquery.Jcrop.min.js new file mode 100644 index 000000000..705920120 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/jcrop/js/jquery.Jcrop.min.js @@ -0,0 +1,2 @@ +(function(n){n.Jcrop=function(t,i){function h(n){return Math.round(n)+"px"}function ft(n){return r.baseClass+"-"+n}function bi(){return n.fx.step.hasOwnProperty("backgroundColor")}function et(t){var i=n(t).offset();return[i.left,i.top]}function nt(n){return[n.pageX-b[0],n.pageY-b[1]]}function ri(t){typeof t!="object"&&(t={}),r=n.extend(r,t),n.each(["onChange","onSelect","onRelease","onDblClick"],function(n,t){typeof r[t]!="function"&&(r[t]=function(){})})}function ui(n,t,i){if(b=et(e),p.setCursor(n==="move"?n:n+"-resize"),n==="move")return p.activateHandlers(di(t),pt,i);var u=s.getFixed(),r=fi(n),f=s.getCorner(fi(r));s.setPressed(s.getCorner(r)),s.setCurrent(f),p.activateHandlers(ki(n,u),pt,i)}function ki(n,t){return function(i){if(r.aspectRatio)switch(n){case"e":i[1]=t.y+1;break;case"w":i[1]=t.y+1;break;case"n":i[0]=t.x+1;break;case"s":i[0]=t.x+1}else switch(n){case"e":i[1]=t.y2;break;case"w":i[1]=t.y2;break;case"n":i[0]=t.x2;break;case"s":i[0]=t.x2}s.setCurrent(i),u.update()}}function di(n){var t=n;return kt.watchKeys(),function(n){s.moveOffset([n[0]-t[0],n[1]-t[1]]),t=n,u.update()}}function fi(n){switch(n){case"n":return"sw";case"s":return"nw";case"e":return"nw";case"w":return"ne";case"ne":return"sw";case"nw":return"se";case"se":return"nw";case"sw":return"ne"}}function ei(n){return function(t){return r.disabled?!1:n==="move"&&!r.allowMove?!1:(b=et(e),ut=!0,ui(n,nt(t)),t.stopPropagation(),t.preventDefault(),!1)}}function oi(n,t,i){var r=n.width(),u=n.height();r>t&&t>0&&(r=t,u=t/n.width()*n.height()),u>i&&i>0&&(u=i,r=i/n.height()*n.width()),l=n.width()/r,a=n.height()/u,n.width(r).height(u)}function ot(n){return{x:n.x*l,y:n.y*a,x2:n.x2*l,y2:n.y2*a,w:n.w*l,h:n.h*a}}function pt(){var n=s.getFixed();n.w>r.minSelect[0]&&n.h>r.minSelect[1]?(u.enableHandles(),u.done()):u.release(),p.setCursor(r.allowSelect?"crosshair":"default")}function si(n){if(r.disabled||!r.allowSelect)return!1;ut=!0,b=et(e),u.disableHandles(),p.setCursor("crosshair");var t=nt(n);return s.setPressed(t),u.update(),p.activateHandlers(gi,pt,n.type.substring(0,5)==="touch"),kt.watchKeys(),n.stopPropagation(),n.preventDefault(),!1}function gi(n){s.setCurrent(n),u.update()}function hi(){var t=n("
<\/div>").addClass(ft("tracker"));return ti&&t.css({opacity:0,backgroundColor:"white"}),t}function nr(n){w.removeClass().addClass(ft("holder")).addClass(n)}function tr(n,t){function b(){window.setTimeout(k,d)}var c=n[0]/l,y=n[1]/a,p=n[2]/l,w=n[3]/a,k;if(!bt){var o=s.flipCoords(c,y,p,w),h=s.getFixed(),e=[h.x,h.y,h.x2,h.y2],i=e,d=r.animationDelay,g=o[0]-e[0],nt=o[1]-e[1],tt=o[2]-e[2],it=o[3]-e[3],f=0,rt=r.swingSpeed;c=i[0],y=i[1],p=i[2],w=i[3],u.animMode(!0),k=function(){return function(){f+=(100-f)/rt,i[0]=Math.round(c+f/100*g),i[1]=Math.round(y+f/100*nt),i[2]=Math.round(p+f/100*tt),i[3]=Math.round(w+f/100*it),f>=99.8&&(f=100),f<100?(yi(i),b()):(u.done(),u.animMode(!1),typeof t=="function"&&t.call(v))}}(),b()}}function vi(n){yi([n[0]/l,n[1]/a,n[2]/l,n[3]/a]),r.onSelect.call(v,ot(s.getFixed())),u.enableHandles()}function yi(n){s.setPressed([n[0],n[1]]),s.setCurrent([n[2],n[3]]),u.update()}function ir(){return ot(s.getFixed())}function rr(){return s.getFixed()}function ur(n){ri(n),gt()}function pi(){r.disabled=!0,u.disableHandles(),u.setCursor("default"),p.setCursor("default")}function wi(){r.disabled=!1,gt()}function fr(){u.done(),p.activateHandlers(null,null)}function er(){w.remove(),c.show(),c.css("visibility","visible"),n(t).removeData("Jcrop")}function or(n,t){u.release(),pi();var i=new Image;i.onload=function(){var u=i.width,s=i.height,h=r.boxWidth,c=r.boxHeight;e.width(u).height(s),e.attr("src",n),k.attr("src",n),oi(e,h,c),o=e.width(),f=e.height(),k.width(o).height(f),d.width(o+rt*2).height(f+rt*2),w.width(o).height(f),g.resize(o,f),wi(),typeof t=="function"&&t.call(v)},i.src=n}function dt(n,t,i){var u=t||r.bgColor;r.bgFade&&bi()&&r.fadeTime&&!i?n.animate({backgroundColor:u},{queue:!1,duration:r.fadeTime}):n.css("backgroundColor",u)}function gt(n){r.allowResize?n?u.enableOnly():u.enableHandles():u.disableHandles(),p.setCursor(r.allowSelect?"crosshair":"default"),u.setCursor(r.allowMove?"move":"default"),r.hasOwnProperty("trueSize")&&(l=r.trueSize[0]/o,a=r.trueSize[1]/f),r.hasOwnProperty("setSelect")&&(vi(r.setSelect),u.done(),delete r.setSelect),g.refresh(),r.bgColor!=li&&(dt(r.shade?g.getShades():w,r.shade?r.shadeColor||r.bgColor:r.bgColor),li=r.bgColor),st!=r.bgOpacity&&(st=r.bgOpacity,r.shade?g.refresh():u.setBgOpacity(st)),ht=r.maxSize[0]||0,ct=r.maxSize[1]||0,lt=r.minSize[0]||0,at=r.minSize[1]||0,r.hasOwnProperty("outerImage")&&(e.attr("src",r.outerImage),delete r.outerImage),u.refresh()}var r=n.extend({},n.Jcrop.defaults),b,ni=navigator.userAgent.toLowerCase(),ti=/msie/.test(ni),ii=/msie [1-6]\./.test(ni),vt,e,v;typeof t!="object"&&(t=n(t)[0]),typeof i!="object"&&(i={}),ri(i);var wt={border:"none",visibility:"visible",margin:0,padding:0,position:"absolute",top:0,left:0},c=n(t),ci=!0;t.tagName=="IMG"?(c[0].width!=0&&c[0].height!=0?(c.width(c[0].width),c.height(c[0].height)):(vt=new Image,vt.src=c[0].src,c.width(vt.width),c.height(vt.height)),e=c.clone().removeAttr("id").css(wt).show(),e.width(c.width()),e.height(c.height()),c.after(e).hide()):(e=c.css(wt).show(),ci=!1,r.shade===null&&(r.shade=!0)),oi(e,r.boxWidth,r.boxHeight);var o=e.width(),f=e.height(),w=n("
").width(o).height(f).addClass(ft("holder")).css({position:"relative",backgroundColor:r.bgColor}).insertAfter(c).append(e);r.addClass&&w.addClass(r.addClass);var k=n("
"),yt=n("
").width("100%").height("100%").css({zIndex:310,position:"absolute",overflow:"hidden"}),tt=n("
").width("100%").height("100%").css("zIndex",320),it=n("
").css({position:"absolute",zIndex:600}).dblclick(function(){var n=s.getFixed();r.onDblClick.call(v,n)}).insertBefore(e).append(yt,tt);ci&&(k=n("").attr("src",e.attr("src")).css(wt).width(o).height(f),yt.append(k)),ii&&it.css({overflowY:"hidden"});var rt=r.boundary,d=hi().width(o+rt*2).height(f+rt*2).css({position:"absolute",top:h(-rt),left:h(-rt),zIndex:290}).mousedown(si),li=r.bgColor,st=r.bgOpacity,ht,ct,lt,at,l,a,ut,bt,ai;b=et(e);var y=function(){function n(){var i={},u=["touchstart","touchmove","touchend"],f=document.createElement("div"),t,n,r;try{for(t=0;tn+e&&(e-=e+n),0>t+s&&(s-=s+t),fo&&(s=o,p=Math.abs((s-n)/c),h=d<0?t-p:p+t)):(s=u,p=tt/c,h=d<0?t-p:t+p,h<0?(h=0,v=Math.abs((h-t)*c),s=k<0?n-v:v+n):h>f&&(h=f,v=Math.abs(h-t)*c,s=k<0?n-v:v+n)),s>n?(s-nw&&(s=n+w),h=h>t?t+(s-n)/c:t-(s-n)/c):sw&&(s=n-w),h=h>t?t+(n-s)/c:t-(n-s)/c),s<0?(n-=s,s=0):s>o&&(n-=s-o,s=o),h<0?(t-=h,h=0):h>f&&(t-=h-f,h=f),y(e(n,t,s,h))}function v(n){return n[0]<0&&(n[0]=0),n[1]<0&&(n[1]=0),n[0]>o&&(n[0]=o),n[1]>f&&(n[1]=f),[Math.round(n[0]),Math.round(n[1])]}function e(n,t,i,r){var u=n,f=i,e=t,o=r;return iht&&(u=s>0?n+ht:n-ht),ct&&Math.abs(h)>ct&&(i=h>0?t+ct:t-ct),at/a&&Math.abs(h)0?t+at/a:t-at/a),lt/l&&Math.abs(s)0?n+lt/l:n-lt/l),n<0&&(u-=n,n-=n),t<0&&(i-=t,t-=t),u<0&&(n-=u,u-=u),i<0&&(t-=i,i-=i),u>o&&(r=u-o,n-=r,u-=r),i>f&&(r=i-f,t-=r,i-=r),n>o&&(r=n-f,i-=r,t-=r),t>f&&(r=t-f,i-=r,t-=r),y(e(n,t,u,i))}function y(n){return{x:n[0],y:n[1],x2:n[2],y2:n[3],w:n[2]-n[0],h:n[3]-n[1]}}var n=0,t=0,u=0,i=0,s,h;return{flipCoords:e,setPressed:p,setCurrent:w,getOffset:b,moveOffset:k,getCorner:d,getFixed:c}}(),g=function(){function nt(n,t){i.left.css({height:h(t)}),i.right.css({height:h(t)})}function v(){return y(s.getFixed())}function y(n){i.top.css({left:h(n.x),width:h(n.w),height:h(n.y)}),i.bottom.css({top:h(n.y2),left:h(n.x),width:h(n.w),height:h(f-n.y2)}),i.right.css({left:h(n.x2),width:h(o-n.x2)}),i.left.css({width:h(n.x)})}function l(){return n("
").css({position:"absolute",backgroundColor:r.shadeColor||r.bgColor}).appendTo(t)}function p(){c||(c=!0,t.insertBefore(e),v(),u.setBgOpacity(1,0,1),k.hide(),b(r.shadeColor||r.bgColor,1),u.isAwake()?a(r.bgOpacity,1):a(1,1))}function b(n,t){dt(g(),n,t)}function d(){c&&(t.remove(),k.show(),c=!1,u.isAwake()?u.setBgOpacity(r.bgOpacity,1,1):(u.setBgOpacity(1,1,1),u.disableHandles()),dt(w,0,1))}function a(n,i){c&&(r.bgFade&&!i?t.animate({opacity:1-n},{queue:!1,duration:r.fadeTime}):t.css({opacity:1-n}))}function tt(){r.shade?p():d(),u.isAwake()&&a(r.bgOpacity)}function g(){return t.children()}var c=!1,t=n("
").css({position:"absolute",zIndex:240,opacity:0}),i={top:l(),left:l().height(f),right:l().height(f),bottom:l()};return{update:v,updateRaw:y,getShades:g,setBgColor:b,enable:p,disable:d,resize:nt,refresh:tt,opacity:a}}(),u=function(){function et(t){var i=n("
").css({position:"absolute",opacity:r.borderOpacity}).addClass(ft(t));return yt.append(i),i}function l(t,i){var r=n("
").mousedown(ei(t)).css({cursor:t+"-resize",position:"absolute",zIndex:i}).addClass("ord-"+t);return y.support&&r.bind("touchstart.jcrop",y.createDragger(t)),tt.append(r),r}function ht(n){var t=r.handleSize,i=l(n,c++).css({opacity:r.handleOpacity}).addClass(ft("handle"));return t&&i.width(t).height(t),i}function ct(n){return l(n,c++).addClass("jcrop-dragbar")}function lt(n){for(var t=0;t').css({position:"fixed",left:"-120px",width:"12px"}).addClass("jcrop-keymgr"),f=n("
").css({position:"absolute",overflow:"hidden"}).append(t);return r.keySupport&&(t.keydown(c).blur(h),ii||!r.fixedSupport?(t.css({position:"absolute",left:"-20px"}),f.append(t).insertBefore(e)):t.insertBefore(e)),{watchKeys:o}}();return y.support&&d.bind("touchstart.jcrop",y.newSelection),tt.hide(),gt(!0),v={setImage:or,animateTo:tr,setSelect:vi,setOptions:ur,tellSelect:ir,tellScaled:rr,setClass:nr,disable:pi,enable:wi,cancel:fr,release:u.release,destroy:er,focus:kt.watchKeys,getBounds:function(){return[o*l,f*a]},getWidgetSize:function(){return[o,f]},getScaleFactor:function(){return[l,a]},getOptions:function(){return r},ui:{holder:w,selection:it}},ti&&w.bind("selectstart",function(){return!1}),c.data("Jcrop",v),v},n.fn.Jcrop=function(t,i){var r;return this.each(function(){if(n(this).data("Jcrop")){if(t==="api")return n(this).data("Jcrop");n(this).data("Jcrop").setOptions(t)}else this.tagName=="IMG"?n.Jcrop.Loader(this,function(){n(this).css({display:"block",visibility:"hidden"}),r=n.Jcrop(this,t),n.isFunction(i)&&i.call(r)}):(n(this).css({display:"block",visibility:"hidden"}),r=n.Jcrop(this,t),n.isFunction(i)&&i.call(r))}),this},n.Jcrop.Loader=function(t,i,r){function e(){f.complete?(u.unbind(".jcloader"),n.isFunction(i)&&i.call(f)):window.setTimeout(e,50)}var u=n(t),f=u[0];u.bind("load.jcloader",e).bind("error.jcloader",function(){u.unbind(".jcloader"),n.isFunction(r)&&r.call(f)}),f.complete&&n.isFunction(i)&&(u.unbind(".jcloader"),i.call(f))},n.Jcrop.defaults={allowSelect:!0,allowMove:!0,allowResize:!0,trackDocument:!0,baseClass:"jcrop",addClass:null,bgColor:"black",bgOpacity:.6,bgFade:!1,borderOpacity:.4,handleOpacity:.5,handleSize:null,aspectRatio:0,keySupport:!0,createHandles:["n","s","e","w","nw","ne","se","sw"],createDragbars:["n","s","e","w"],createBorders:["n","s","e","w"],drawBorders:!0,dragEdges:!0,fixedSupport:!0,touchSupport:null,shade:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onDblClick:function(){},onRelease:function(){}}})(jQuery); +//@ sourceMappingURL=jquery.Jcrop.min.js.map \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/jcrop/js/jquery.Jcrop.min.js.map b/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/jcrop/js/jquery.Jcrop.min.js.map new file mode 100644 index 000000000..13a0f4d83 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Scripts/jcrop/js/jquery.Jcrop.min.js.map @@ -0,0 +1,8 @@ +{ +"version":3, +"file":"jquery.Jcrop.min.js", +"lineCount":1, +"mappings":"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", +"sources":["jquery.Jcrop.js"], +"names":["$","Jcrop","$.Jcrop","obj","opt","px","n","Math","round","cssClass","cl","options","baseClass","supportsColorFade","fx","step","hasOwnProperty","getPos","pos","offset","left","top","mouseAbs","e","pageX","docOffset","pageY","setOptions","extend","each","i","startDragMode","mode","touch","$img","Tracker","setCursor","activateHandlers","createMover","doneSelect","fc","Coords","getFixed","opp","oppLockCorner","opc","getCorner","setPressed","setCurrent","dragmodeHandler","f","aspectRatio","y","x","y2","x2","Selection","update","lloc","KeyManager","watchKeys","moveOffset","ord","createDragger","disabled","allowMove","btndown","stopPropagation","preventDefault","presize","$obj","w","h","nw","width","nh","height","xscale","yscale","unscale","c","minSelect","enableHandles","done","release","allowSelect","newSelection","disableHandles","selectDrag","type","substring","newTracker","trk","addClass","is_msie","css","setClass","cname","$div","removeClass","animateTo","a","callback","queueAnimator","window","setTimeout","animator","interv","x1","y1","animating","animto","flipCoords","initcr","animat","animationDelay","ix1","iy1","ix2","iy2","pcent","velocity","swingSpeed","animMode","setSelectRaw","call","api","setSelect","rect","onSelect","l","tellSelect","tellScaled","setOptionsNew","interfaceUpdate","disableCrop","enableCrop","cancelCrop","destroy","remove","$origimg","show","removeData","setImage","src","img","Image","onload","img.onload","iw","ih","bw","boxWidth","bh","boxHeight","attr","$img2","boundx","boundy","$trk","bound","Shade","resize","colorChangeMacro","color","now","mycolor","bgColor","bgFade","fadeTime","animate","alt","allowResize","enableOnly","trueSize","refresh","bgcolor","shade","getShades","shadeColor","bgopacity","bgOpacity","setBgOpacity","xlimit","maxSize","ylimit","xmin","minSize","ymin","outerImage","defaults","_ua","navigator","userAgent","toLowerCase","test","ie6mode","tempImage","img_css","img_mode","tagName","clone","removeAttr","after","hide","insertAfter","append","$img_holder","$hdl_holder","$sel","dblclick","onDblClick","insertBefore","boundary","mousedown","shift_down","Touch","hasTouchSupport","support","events","el","document","createElement","eventName","isSupported","length","setAttribute","touchstart","touchend","touchmove","err","detectSupport","touchSupport","cfilter","originalEvent","changedTouches","rebound","ox","oy","getOffset","getRect","aspect","min_x","max_x","max_y","rw","rh","rwa","abs","rha","real_ratio","xx","yy","makeObj","p","xa","xb","ya","yb","xsize","ysize","delta","resizeShades","shades","right","updateAuto","updateShade","bottom","createShade","appendTo","holder","enableShade","enabled","setBgColor","isAwake","setOpacity","disableShade","opacity","refreshAll","children","insertBorder","jq","borderOpacity","dragDiv","zi","bind","insertHandle","hs","handleSize","div","hdep","handleOpacity","insertDragbar","createDragbars","li","dragbar","createBorders","borders","createHandles","handle","moveto","updateVisible","select","awake","updateRaw","onChange","force","onRelease","showHandles","seehandles","v","$track","dragEdges","isArray","drawBorders","currentTarget","hasClass","cursor","toFront","trackTouchMove","trackTouchEnd","trackDoc","trackMove","trackUp","toBack","unbind","onMove","onDone","move","t","trackDocument","mousemove","mouseup","mouseout","before","keySupport","$keymgr","focus","onBlur","doNudge","parseKey","ctrlKey","metaKey","shiftKey","nudge","keyCode","$keywrap","keydown","blur","fixedSupport","getBounds","getWidgetSize","getScaleFactor","getOptions","data","fn","$.fn.Jcrop","Loader","isFunction","$.Jcrop.Loader","imgobj","success","error","completeCheck","complete","jQuery"] +} diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/Web.config b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/Web.config new file mode 100644 index 000000000..770adfab5 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/Web.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/image-editor.css b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/image-editor.css new file mode 100644 index 000000000..b252b3967 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/image-editor.css @@ -0,0 +1,57 @@ +#image-editor-toolbar { + padding: 0 0 4px 0; + display: block; +} + +#image-editor-options { + padding: 0 0 4px 0; + display: block; +} + +#image-editor-container { + padding: 30px; + margin-top:10px; + background-color: rgb(62, 70, 74); +} + +#image-editor-options-container { + display: none; +} + +#image-editor-image { + display: block; + margin-left: auto; + margin-right: auto; +} + +.canvas-shadow { + -moz-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.80); + -webkit-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.80); + box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.80); +} + +.editor-shadow { + -moz-box-shadow: inset 0px 0px 12px rgba(0, 0, 0, 0.80); + -webkit-box-shadow: inset 0px 0px 12px rgba(0, 0, 0, 0.80); + box-shadow: inset 0px 0px 12px rgba(0, 0, 0, 0.80); +} + +/* FILTERS */ +.filters { +} + +.filter { + float: left; + margin-right: 20px; +} + +.filter > span { + display: inline-block; + width: 100px; +} + +.slider { + display: inline-block; + width: 200px; + margin-top: 10px; +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/Jcrop.gif b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/Jcrop.gif new file mode 100644 index 0000000000000000000000000000000000000000..72ea7ccb5321d5384d70437cfaac73011237901e GIT binary patch literal 329 zcmZ?wbhEHb9b#5NV>2k zBC~b@b~P=nNfWAe-b%_i6tS^-1y(h@EsB~1TqDA_h@fkxG$bHgvj}VxE1JLgr!*!^ ILUxTc0Q$^Q5C8xG literal 0 HcmV?d00001 diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/jquery.Jcrop.css b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/jquery.Jcrop.css new file mode 100644 index 000000000..95f8b9cfc --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/jquery.Jcrop.css @@ -0,0 +1,165 @@ +/* jquery.Jcrop.css v0.9.12 - MIT License */ +/* + The outer-most container in a typical Jcrop instance + If you are having difficulty with formatting related to styles + on a parent element, place any fixes here or in a like selector + + You can also style this element if you want to add a border, etc + A better method for styling can be seen below with .jcrop-light + (Add a class to the holder and style elements for that extended class) +*/ +.jcrop-holder { + direction: ltr; + text-align: left; +} +/* Selection Border */ +.jcrop-vline, +.jcrop-hline { + background: #ffffff url("Jcrop.gif"); + font-size: 0; + position: absolute; +} +.jcrop-vline { + height: 100%; + width: 1px !important; +} +.jcrop-vline.right { + right: 0; +} +.jcrop-hline { + height: 1px !important; + width: 100%; +} +.jcrop-hline.bottom { + bottom: 0; +} +/* Invisible click targets */ +.jcrop-tracker { + height: 100%; + width: 100%; + /* "turn off" link highlight */ + -webkit-tap-highlight-color: transparent; + /* disable callout, image save panel */ + -webkit-touch-callout: none; + /* disable cut copy paste */ + -webkit-user-select: none; +} +/* Selection Handles */ +.jcrop-handle { + background-color: #333333; + border: 1px #eeeeee solid; + width: 7px; + height: 7px; + font-size: 1px; +} +.jcrop-handle.ord-n { + left: 50%; + margin-left: -4px; + margin-top: -4px; + top: 0; +} +.jcrop-handle.ord-s { + bottom: 0; + left: 50%; + margin-bottom: -4px; + margin-left: -4px; +} +.jcrop-handle.ord-e { + margin-right: -4px; + margin-top: -4px; + right: 0; + top: 50%; +} +.jcrop-handle.ord-w { + left: 0; + margin-left: -4px; + margin-top: -4px; + top: 50%; +} +.jcrop-handle.ord-nw { + left: 0; + margin-left: -4px; + margin-top: -4px; + top: 0; +} +.jcrop-handle.ord-ne { + margin-right: -4px; + margin-top: -4px; + right: 0; + top: 0; +} +.jcrop-handle.ord-se { + bottom: 0; + margin-bottom: -4px; + margin-right: -4px; + right: 0; +} +.jcrop-handle.ord-sw { + bottom: 0; + left: 0; + margin-bottom: -4px; + margin-left: -4px; +} +/* Dragbars */ +.jcrop-dragbar.ord-n, +.jcrop-dragbar.ord-s { + height: 7px; + width: 100%; +} +.jcrop-dragbar.ord-e, +.jcrop-dragbar.ord-w { + height: 100%; + width: 7px; +} +.jcrop-dragbar.ord-n { + margin-top: -4px; +} +.jcrop-dragbar.ord-s { + bottom: 0; + margin-bottom: -4px; +} +.jcrop-dragbar.ord-e { + margin-right: -4px; + right: 0; +} +.jcrop-dragbar.ord-w { + margin-left: -4px; +} +/* The "jcrop-light" class/extension */ +.jcrop-light .jcrop-vline, +.jcrop-light .jcrop-hline { + background: #ffffff; + filter: alpha(opacity=70) !important; + opacity: .70!important; +} +.jcrop-light .jcrop-handle { + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + background-color: #000000; + border-color: #ffffff; + border-radius: 3px; +} +/* The "jcrop-dark" class/extension */ +.jcrop-dark .jcrop-vline, +.jcrop-dark .jcrop-hline { + background: #000000; + filter: alpha(opacity=70) !important; + opacity: 0.7 !important; +} +.jcrop-dark .jcrop-handle { + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + background-color: #ffffff; + border-color: #000000; + border-radius: 3px; +} +/* Simple macro to turn off the antlines */ +.solid-line .jcrop-vline, +.solid-line .jcrop-hline { + background: #ffffff; +} +/* Fix for twitter bootstrap et al. */ +.jcrop-holder img, +img.jcrop-preview { + max-width: none; +} diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/jquery.Jcrop.min.css b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/jquery.Jcrop.min.css new file mode 100644 index 000000000..edc76b2b3 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/jcrop/css/jquery.Jcrop.min.css @@ -0,0 +1,29 @@ +/* jquery.Jcrop.min.css v0.9.12 (build:20130126) */ +.jcrop-holder{direction:ltr;text-align:left;} +.jcrop-vline,.jcrop-hline{background:#FFF url(Jcrop.gif);font-size:0;position:absolute;} +.jcrop-vline{height:100%;width:1px!important;} +.jcrop-vline.right{right:0;} +.jcrop-hline{height:1px!important;width:100%;} +.jcrop-hline.bottom{bottom:0;} +.jcrop-tracker{-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;-webkit-user-select:none;height:100%;width:100%;} +.jcrop-handle{background-color:#333;border:1px #EEE solid;font-size:1px;height:7px;width:7px;} +.jcrop-handle.ord-n{left:50%;margin-left:-4px;margin-top:-4px;top:0;} +.jcrop-handle.ord-s{bottom:0;left:50%;margin-bottom:-4px;margin-left:-4px;} +.jcrop-handle.ord-e{margin-right:-4px;margin-top:-4px;right:0;top:50%;} +.jcrop-handle.ord-w{left:0;margin-left:-4px;margin-top:-4px;top:50%;} +.jcrop-handle.ord-nw{left:0;margin-left:-4px;margin-top:-4px;top:0;} +.jcrop-handle.ord-ne{margin-right:-4px;margin-top:-4px;right:0;top:0;} +.jcrop-handle.ord-se{bottom:0;margin-bottom:-4px;margin-right:-4px;right:0;} +.jcrop-handle.ord-sw{bottom:0;left:0;margin-bottom:-4px;margin-left:-4px;} +.jcrop-dragbar.ord-n,.jcrop-dragbar.ord-s{height:7px;width:100%;} +.jcrop-dragbar.ord-e,.jcrop-dragbar.ord-w{height:100%;width:7px;} +.jcrop-dragbar.ord-n{margin-top:-4px;} +.jcrop-dragbar.ord-s{bottom:0;margin-bottom:-4px;} +.jcrop-dragbar.ord-e{margin-right:-4px;right:0;} +.jcrop-dragbar.ord-w{margin-left:-4px;} +.jcrop-light .jcrop-vline,.jcrop-light .jcrop-hline{background:#FFF;filter:alpha(opacity=70)!important;opacity:.70!important;} +.jcrop-light .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#000;border-color:#FFF;border-radius:3px;} +.jcrop-dark .jcrop-vline,.jcrop-dark .jcrop-hline{background:#000;filter:alpha(opacity=70)!important;opacity:.7!important;} +.jcrop-dark .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#FFF;border-color:#000;border-radius:3px;} +.solid-line .jcrop-vline,.solid-line .jcrop-hline{background:#FFF;} +.jcrop-holder img,img.jcrop-preview{max-width:none;} diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/orchard-imageeditor-admin.css b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/orchard-imageeditor-admin.css new file mode 100644 index 000000000..850316896 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Styles/orchard-imageeditor-admin.css @@ -0,0 +1,435 @@ +/* Reset +***************************************************************/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, button, submit { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} + +/* Remember focus styles! */ +:focus { outline: 0; } + +body { line-height: 1; color: black; background: rgb(243, 244, 245); } +ol, ul { list-style: none; } + +/* Tables still need 'cellspacing="0"' in the markup */ +table { border-collapse: separate; border-spacing: 0; } +caption, th, td { text-align: left; font-weight: normal; } + +blockquote:before, blockquote:after, +q:before, q:after { content: ""; } +blockquote, q { quotes: "" ""; } + +/* HTML 5 elements as block */ +header, footer, aside, nav, article { display: block; } +/* end: reset */ + +/* Clearing Floats +***************************************************************/ + +.group:after, .zone-content:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + + +/* General +***************************************************************/ + +/* Default font settings. +The font-size 81.3% sets the base font to 13px + +Pixels EMs Percent Points +1px 0.077em 7.7% 1pt +2px 0.154em 15.4% 2pt +3px 0.231em 23.1% 3pt +4px 0.308em 30.8% 3pt +5px 0.385em 38.5% 4pt +6px 0.462em 46.2% 5pt +7px 0.538em 53.8% 5pt +8px 0.615em 61.5% 6pt +9px 0.692em 69.2% 7pt +10px 0.769em 76.9% 8pt +11px 0.846em 84.6% 8pt +12px 0.923em 92.3% 9pt +13px 1em 100% 10pt +14px 1.077em 107.7% 11pt +15px 1.154em 115.4% 11pt +16px 1.231em 123.1% 12pt +17px 1.308em 130.8% 13pt +18px 1.385em 138.5% 14pt +19px 1.462em 146.2% 14pt +20px 1.538em 153.8% 15pt +21px 1.615em 161.5% 16pt +22px 1.692em 169.2% 17pt +23px 1.769em 176.9% 17pt +24px 1.846em 184.6% 18pt +*/ + +html, body { height:100%; box-sizing: border-box; } + +html { + color:#333; +} + +body { + font-size: 81.3%; + color: #333; + font-family: Segoe UI,Trebuchet,Arial,Sans-Serif; + line-height:1.6em; + margin:0 auto; + padding:30px; +} + +/*Hide shape tracing*/ +#shape-tracing-container {display:none;} + +/* Headings */ +h1,h2,h3,h4,h5,h6 { font-weight: normal;} + +h1 { font-size: 1.769em; } +h2 { font-size: 1.308em; } +h3 { font-size: 1.231em; } +h4 { font-size: 1.154em; } +h5 { font-size: 1.077em; } +h6 { font-size: 1em; } + +h1, h2, h3, h4, h5, legend { + padding:.6px 0; + font-style: normal; + font-weight:normal; +} + +h1 img, h2 img, h3 img, +h4 img, h5 img, h6 img { + margin: 0; +} + +.small { width:4em; } +.medium { width:26em; } +.large { width:99% } + +#content { + background-color: #fff; + padding: 16px 24px; + margin:8px 0 0 0; + border: 1px solid #e4e5e6; + clear:both; + + /*CSS3 properties*/ + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; +} + +/* Forms +***************************************************************/ + +form { margin: 0; padding: 0;} +legend { font-size: 1.231em; font-weight: normal; border:none;} +fieldset { padding:6px 0 0; margin:0 0 12px 0; border: 0px solid #dbdbdb; } +label { font-weight:normal; display:block; padding: 0 0 0.3em 0; } +label.forcheckbox { margin:0 0 0 .4em; display:inline; } +label.required:after {margin-left: 1ex; content: "*"; color: red; } + +form.inline, form.inline fieldset { /* todo: (heskew) need something other than .inline ... */ + display:inline; +} +form.inline fieldset { + margin:0; +} +.bulk-actions { + display:inline; + height:auto; + margin:0 4px 0 0; + padding:0 0 0 0; +} + +input[type="checkbox"]:focus, input[type="radio"]:focus { + outline:1px dotted #666d51; +} + +input[readonly] { + background-color: #EBEBE4; + color: #545454; +} + +legend span { + font-weight:normal; +} +.bulk-actions label, .bulk-items h3, label.sub { + display:inline; +} +label.bulk-order { + text-transform:lowercase; +} +label span { + font-weight:normal; +} +label input { + vertical-align:text-top; +} +.hint { + display:block; + font-size:0.923em; + color:#7c7c7c; +} +/* todo: (heskew) try to get .text on stuff like .text-box */ +select, textarea, input.text, input.textMedium, input.text-small, input.text-box { + font-family:inherit; + padding:3px; + border:1px solid #bdbcbc; + font-family:inherit; + font-size:inherit; +} +input.text, input.textMedium, input.text-box { + line-height:1.2em; +} +/*Are we using the two classes below?*/ +input.text-small { + width:4em; +} +input.textMedium { + width:26em; +} +select { + padding:1px; +} +select:focus, textarea:focus, input.text:focus, input.text-box:focus, input.text-small:focus, input.textMedium:focus { + border-color:#666d51; +} +input.check-box { + margin-left:0; + vertical-align:-.1em; +} +input.large.text, textarea, fieldset { + clear:both; +} + +textarea { + min-height:8em; +} +#main input.large.text, #main textarea { + width:99%; +} +#main .primary input.large.text, #main .primary textarea { + margin:0; + padding:4px; + width:98.8%; +} +/* todo: (heskew) move editor specific style elsewhere */ +.primary .mceEditor { + display:block; + margin:0; +} + +/*----buttons----*/ +button.remove, .remove.button, .remove.button:link, .remove.button:visited { + background-color:#DECCCA; + background-image:url(images/tableHeaderBackgroundRed.gif); + border-color:#d6c9c7; + color:#5c3732; +} +button.remove:hover, .remove.button:hover, +button.remove:active, .remove.button:active, +button.remove:focus, .remove.button:focus { + background:#8f7c79; + border-color:#6e5551; + color:#faedeb; +} +button.remove:focus::-moz-focus-inner, .remove.button:focus::-moz-focus-inner { + border-color:#8f7c79; +} +.delete.button { + float:right; +} +.button.grey { + color:#5d615d; + background:#f5f5f5; + border:1px solid #999; + + /*CSS3 properties*/ + text-shadow:none; + + -webkit-box-shadow: inset 0px 0px 1px rgba(255, 255, 255, 1.0); + -moz-box-shadow: inset 0px 0px 1px rgba(255, 255, 255, 1.0); + box-shadow: inset 0px 0px 1px rgba(255, 255, 255, 1.0); + + /*----In ie the first couplet sets the alpha value so 00=transparent and ff=opaque)----*/ + filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr='#fff5f5f5', endColorstr='#ffd9d9d9'); + background: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(245, 245, 245, 1.0)), to(rgba(217, 217, 217, 1.0))); + background: -moz-linear-gradient(top, rgba(245, 245, 245, 1.0), rgba(217, 217, 217, 1.0)); + + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; +} +button, .button, a.button { + background:#6a7b42; + border:1px solid #487328; + color:#fff; + cursor: pointer; + display: inline-block; + font: 12px Arial,Helvetica,sans-serif; + padding: 5px 14px 5px 14px; + + /*position: relative;*/ + text-align: center; + text-decoration: none; + + /*----CSS3 properties----*/ + text-shadow: rgba(40,53,9,.2) 0px 0px 1px; + -webkit-box-shadow: inset 0px 0px 1px rgba(255, 255, 255, 1.0), 1px 1px 1px rgba(102, 102, 102, 0.2); + -moz-box-shadow: inset 0px 0px 1px rgba(255, 255, 255, 1.0), 1px 1px 1px rgba(102, 102, 102, 0.2); + box-shadow: inset 0px 0px 1px rgba(255, 255, 255, 1.0), 1px 1px 1px rgba(102, 102, 102, 0.2); + + + /*----In ie the first couplet sets the alpha value so 00=transparent and ff=opaque)----*/ + filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr='#ff9bb36c', endColorstr='#ff809f43'); + background: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(155, 179, 108, 1.0)), to(rgba(128, 159, 67, 1.0))); + background: -moz-linear-gradient(top, rgba(155, 179, 108, 1.0), rgba(128, 159, 67, 1.0)); + + /*test - base green in pallet is 155,179,108*/ + background: -moz-linear-gradient(top, rgba(155, 179, 108, 1.0), rgba(133, 154, 93, 1.0)); + + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; +} + +.button, a.button /* For link buttons */ +{ + padding: 5px 14px 5px 14px; +} + +button, input.button, x:-moz-any-link { + padding: 3px 14px 3px 14px; + } + +button:hover, .button:hover, a.button:hover { + border-color:#3a822e; + color:#eefcec; + text-decoration:none; + background: #809f43; + + /*CSS3 properties*/ + filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr='#ff6e7f45', endColorstr='#ff6a7b42'); + background: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(110, 127, 69, 1.0)), to(rgba(106, 123, 66, 1.0))); + background: -moz-linear-gradient(top, rgba(110, 127, 69, 1.0), rgba(106, 123, 66, 1.0)); +} + +button:active, .buton:active, a.button:active { + text-decoration:none; + background:#6a7b42; + border:1px solid #487328; + color:#fff; + + /*CSS3 properties*/ + text-shadow: rgba(0,0,0,.5) 0px 0px 1px; + filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr='#ff9bb36c', endColorstr='#ff809f43'); + background: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(155, 179, 108, 1.0)), to(rgba(128, 159, 67, 1.0))); + background: -moz-linear-gradient(top, rgba(155, 179, 108, 1.0), rgba(128, 159, 67, 1.0)); +} +button:focus::-moz-focus-inner, .button:focus::-moz-focus-inner { + border: 1px dotted transparent; +} +/*disabled*/ +.button.disabled, .button.disabled:visited, .button.disabled:hover, .button.disabled:active, .button.disabled:focus { + background-color:#eee; + border:1px solid #ababab; + color:#ababab; + cursor:default; + + filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr='#ffeeeeee', endColorstr='#ffeeeeee'); + background: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(238, 238, 238, 1.0)), to(rgba(238, 238, 238, 1.0))); + background: -moz-linear-gradient(top, rgba(238, 238, 238, 1.0), rgba(238, 238, 238, 1.0)); + + text-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +/* and allow all of that button style to be undone and beyond - to look like a link */ +button.link { + background:none; + border:0; + padding:inherit; + text-shadow:none; + -webkit-box-shadow:none; + -moz-box-shadow:none; + box-shadow:none; + filter:none; + -webkit-border-radius:0; + -moz-border-radius:0; + border-radius:0; +} +.cancel { + margin:0 0 0 .93em; +} +.manage { + float:right; + margin-bottom: 16px; +} +.actions { + clear:right; + padding:0; + text-align:right; +} +.item-properties.actions { + margin: -10px 0 10px 0; +} +.contentItems .actions li { + background:inherit; + border:0; + padding:0; +} +.actions .construct { + float:left; +} +.actions .destruct { + float:right; +} +.manage a.button { + float:right; + height:inherit; + margin-left:4px; +} + +.options +{ + margin: 12px 0px 12px 0px; +} + +.options span /* This is just a fix. We need to fix the base HTML */ +{ + display: block; + margin: 12px 0 0 0; +} + +.options span.hint /* This is just a fix. We need to fix the base HTML */ +{ + display: block; + margin: 0 0 0 0; +} + +.options input[type="text"] /* This is just a fix. We need to fix the base HTML */ +{ + width:26em; +} diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Admin/Edit.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Admin/Edit.cshtml new file mode 100644 index 000000000..357b900cd --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Admin/Edit.cshtml @@ -0,0 +1,24 @@ + + + + + @{ + Style.Include("orchard-imageeditor-admin.css"); + // copy the resulting HTML so that resources can be registered before the + // header is rendered + var content = Display(Model); + } + + @Display.Metas() + @Display.HeadScripts() + @Display.HeadLinks() + @Display.StyleSheetLinks() + + +
+ @content +
+ + @Display.FootScripts() + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Content-ImageEditor.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Content-ImageEditor.cshtml new file mode 100644 index 000000000..4a63cf40f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Content-ImageEditor.cshtml @@ -0,0 +1,50 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@model dynamic +@{ + Script.Require("jQuery"); + Script.Require("jQueryUI"); + Style.Require("jQueryUI_Orchard"); + Script.Include("~/Modules/Orchard.ImageEditor/Scripts/image.editor.js"); + Style.Include("~/Modules/Orchard.ImageEditor/Styles/image.editor.css"); + + ContentItem media = Model.MediaContentItem; + var mediaPart = media.As(); + var imagePart = media.As(); +} + + + + +
+ +
+ @if (Model.Buttons != null) { + @Display(Model.Buttons) + } +
+ +
+
+ @if (Model.Options != null) { + @Display(Model.Options) + } +
+
+ +
+
+ @**@ + +
+
+ +
+
+ + @T("Close") +
+ + +@Html.AntiForgeryTokenOrchard() + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Crop.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Crop.cshtml new file mode 100644 index 000000000..e6aedfc80 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Crop.cshtml @@ -0,0 +1,7 @@ +@{ + Script.Include("~/Modules/Orchard.ImageEditor/Scripts/image.editor-crop.js"); + Script.Include("~/Modules/Orchard.ImageEditor/Scripts/jcrop/js/jquery.Jcrop.min.js"); + Style.Include("~/Modules/Orchard.ImageEditor/Styles/jcrop/css/jquery.Jcrop.css"); +} + + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.CropOptions.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.CropOptions.cshtml new file mode 100644 index 000000000..2c18ed646 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.CropOptions.cshtml @@ -0,0 +1,26 @@ +@using Orchard.ImageEditor.Models +@{ + ImageEditorPart imageEditorPart = Model.ContentPart; +} + + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Effects.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Effects.cshtml new file mode 100644 index 000000000..acfdd54e3 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Effects.cshtml @@ -0,0 +1,101 @@ + +@{ + Script.Include("caman/caman.full.min.js"); +} + +@using (Script.Foot()) { + + +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.EffectsOptions.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.EffectsOptions.cshtml new file mode 100644 index 000000000..62692b096 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.EffectsOptions.cshtml @@ -0,0 +1,28 @@ +@using Orchard.ImageEditor.Models +@{ + ImageEditorPart imageEditorPart = Model.ContentPart; +} + + + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Filter.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Filter.cshtml new file mode 100644 index 000000000..3f4b82768 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Filter.cshtml @@ -0,0 +1,120 @@ + +@{ + Script.Include("caman/caman.full.min.js"); +} + +@using (Script.Foot()) { + + +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.FilterOptions.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.FilterOptions.cshtml new file mode 100644 index 000000000..0de843fc8 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.FilterOptions.cshtml @@ -0,0 +1,63 @@ +@using Orchard.ImageEditor.Models +@{ + ImageEditorPart imageEditorPart = Model.ContentPart; +} + + + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Resize.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Resize.cshtml new file mode 100644 index 000000000..8444a18f0 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.Resize.cshtml @@ -0,0 +1,82 @@ + + +@using (Script.Foot()) { + + +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.ResizeOptions.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.ResizeOptions.cshtml new file mode 100644 index 000000000..19595f649 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.ResizeOptions.cshtml @@ -0,0 +1,28 @@ +@using Orchard.ImageEditor.Models +@{ + ImageEditorPart imageEditorPart = Model.ContentPart; +} + + + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.cshtml b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.cshtml new file mode 100644 index 000000000..bbc6139f1 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Parts/Image.Editor.cshtml @@ -0,0 +1,8 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + ImagePart imagePart = Model.ContentPart; +} + +@Html.ActionLink(T("Edit").Text, "Index", "Admin", new { id = imagePart.Id, area = "Orchard.ImageEditor" }, new {}) + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Web.config b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Web.config new file mode 100644 index 000000000..b7d215131 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Views/Web.config @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.ImageEditor/Web.config b/src/Orchard.Web/Modules/Orchard.ImageEditor/Web.config new file mode 100644 index 000000000..88b84a792 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ImageEditor/Web.config @@ -0,0 +1,41 @@ + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.Media/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.Media/AdminMenu.cs index 38d074bfc..c64cfbe04 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.Media/AdminMenu.cs @@ -14,7 +14,7 @@ namespace Orchard.Media { public void GetNavigation(NavigationBuilder builder) { builder.AddImageSet("media") .Add(T("Media"), "6", - menu => menu.Add(T("Media"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.Media" }) + menu => menu.Add(T("Media Storage"), "1", item => item.Action("Index", "Admin", new { area = "Orchard.Media" }) .Permission(Permissions.ManageMedia))); } } diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/AdminMenu.cs new file mode 100644 index 000000000..3e7f759a5 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/AdminMenu.cs @@ -0,0 +1,21 @@ +using Orchard.Localization; +using Orchard.UI.Navigation; + +namespace Orchard.MediaLibrary { + public class AdminMenu : INavigationProvider { + public Localizer T { get; set; } + + public AdminMenu() { + T = NullLocalizer.Instance; + } + + public string MenuName { get { return "admin"; } } + + public void GetNavigation(NavigationBuilder builder) { + builder.AddImageSet("media") + .Add(T("Media"), "6", + menu => menu.Add(T("Media"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.MediaLibrary", id = (int?)null }) + .Permission(Permissions.ManageMediaContent))); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs new file mode 100644 index 000000000..fc2d1f9b6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs @@ -0,0 +1,100 @@ +using System.Linq; +using System.Web.Mvc; +using Orchard.ContentManagement; +using Orchard.Localization; +using Orchard.Logging; +using Orchard.MediaLibrary.Models; +using Orchard.MediaLibrary.Services; +using Orchard.MediaLibrary.ViewModels; +using Orchard.Mvc; +using Orchard.Themes; +using Orchard.UI.Navigation; +using Orchard.Utility.Extensions; + +namespace Orchard.MediaLibrary.Controllers { + [ValidateInput(false)] + public class AdminController : Controller { + private readonly IMediaLibraryService _mediaLibraryService; + private readonly INavigationManager _navigationManager; + + public AdminController( + IOrchardServices services, + IMediaLibraryService mediaLibraryService, + INavigationManager navigationManager ) { + _mediaLibraryService = mediaLibraryService; + _navigationManager = navigationManager; + Services = services; + + T = NullLocalizer.Instance; + Logger = NullLogger.Instance; + } + + public IOrchardServices Services { get; set; } + public Localizer T { get; set; } + public ILogger Logger { get; set; } + + public ActionResult Index(int? id, bool dialog = false) { + var viewModel = new MediaManagerIndexViewModel { + DialogMode = dialog, + Folders = _mediaLibraryService.GetMediaFolders(), + Folder = id, + Hierarchy = id.HasValue ? _mediaLibraryService.GetMediaFolderHierarchy(id.Value) : Enumerable.Empty() + }; + + if (!id.HasValue && viewModel.Folders.Any()) { + viewModel.Folder = viewModel.Folders.First().TermId; + } + + return View(viewModel); + } + + public ActionResult Import(int id, bool dialog = false) { + var mediaProviderMenu = _navigationManager.BuildMenu("mediaproviders"); + var imageSets = _navigationManager.BuildImageSets("mediaproviders"); + + var hierarchy = _mediaLibraryService.GetMediaFolderHierarchy(id); + + var viewModel = new MediaManagerImportViewModel { + DialogMode = dialog, + Menu = mediaProviderMenu, + Hierarchy = hierarchy.ToReadOnlyCollection(), + ImageSets = imageSets + }; + + return View(viewModel); + } + + [Themed(false)] + public ActionResult MediaItems(int id, int skip = 0, int count = 0) { + var mediaParts = _mediaLibraryService.GetMediaContentItemsForLocation(id, skip, count); + var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCountForLocation(id); + + var mediaItems = mediaParts.Select(x => new MediaManagerMediaItemViewModel { + MediaPart = x, + Shape = Services.ContentManager.BuildDisplay(x, "Thumbnail") + }).ToList(); + + var viewModel = new MediaManagerMediaItemsViewModel { + MediaItems = mediaItems, + MediaItemsCount = mediaPartsCount + }; + + return View(viewModel); + } + + [Themed(false)] + public ActionResult MediaItem(int id, string displayType = "SummaryAdmin") { + var contentItem = Services.ContentManager.Get(id, VersionOptions.Latest); + + if (contentItem == null) + return HttpNotFound(); + + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, contentItem, T("Cannot edit media"))) + return new HttpUnauthorizedResult(); + + dynamic model = Services.ContentManager.BuildDisplay(contentItem, displayType); + + return new ShapeResult(this, model); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs new file mode 100644 index 000000000..24e59f0b9 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Web.Mvc; +using Orchard.MediaLibrary.Providers.ClientStorage; +using Orchard.MediaLibrary.Services; +using Orchard.Themes; +using Orchard.UI.Admin; + +namespace Orchard.MediaLibrary.Controllers { + [Admin, Themed(false)] + public class ClientStorageController : Controller { + private readonly IMediaLibraryService _mediaLibraryService; + + public ClientStorageController(IMediaLibraryService mediaManagerService) { + _mediaLibraryService = mediaManagerService; + } + + public ActionResult Index(int id) { + + return View(id); + } + + [HttpPost] + public ActionResult Upload(int id) { + var statuses = new List(); + + // Loop through each file in the request + for (int i = 0; i < HttpContext.Request.Files.Count; i++) { + // Pointer to file + var file = HttpContext.Request.Files[i]; + var filename = Path.GetFileName(file.FileName); + + // if the file has been pasted, provide a default name + if (filename == "blob") { + filename = "clipboard.png"; + } + + var mediaPart = _mediaLibraryService.ImportStream(id, file.InputStream, filename); + + statuses.Add(new { + id = mediaPart.Id, + name = mediaPart.Title, + type = mediaPart.MimeType, + size = file.ContentLength, + progress = 1.0, + url= mediaPart.Resource, + }); + } + + // Return JSON + return Json(statuses, JsonRequestBehavior.AllowGet); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/FolderController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/FolderController.cs new file mode 100644 index 000000000..57b819574 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/FolderController.cs @@ -0,0 +1,143 @@ +using System; +using System.Linq; +using System.Web.Mvc; +using Orchard.Core.Contents.Controllers; +using Orchard.Localization; +using Orchard.Logging; +using Orchard.MediaLibrary.Models; +using Orchard.MediaLibrary.Services; +using Orchard.MediaLibrary.ViewModels; +using Orchard.UI.Admin; +using Orchard.UI.Notify; + +namespace Orchard.MediaLibrary.Controllers { + [Admin] + public class FolderController : Controller { + private readonly IMediaLibraryService _mediaLibraryService; + + public FolderController(IOrchardServices services, IMediaLibraryService mediaManagerService) { + _mediaLibraryService = mediaManagerService; + + Services = services; + Logger = NullLogger.Instance; + T = NullLocalizer.Instance; + } + + public IOrchardServices Services { get; set; } + public ILogger Logger { get; set; } + public Localizer T { get; set; } + + public ActionResult Create(int? id) { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't create media folder"))) + return new HttpUnauthorizedResult(); + + var viewModel = new MediaManagerFolderCreateViewModel { + Hierarchy = id.HasValue ? _mediaLibraryService.GetMediaFolderHierarchy(id.Value) : Enumerable.Empty(), + ParentFolderId = id + }; + + return View(viewModel); + } + + [HttpPost, ActionName("Create")] + public ActionResult Create() { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't create media folder"))) + return new HttpUnauthorizedResult(); + + var viewModel = new MediaManagerFolderCreateViewModel(); + UpdateModel(viewModel); + + try { + _mediaLibraryService.CreateFolder(viewModel.ParentFolderId, viewModel.Name); + Services.Notifier.Information(T("Media folder created")); + } + catch (ArgumentException argumentException) { + Services.Notifier.Error(T("Creating Folder failed: {0}", argumentException.Message)); + Services.TransactionManager.Cancel(); + return View(viewModel); + } + + return RedirectToAction("Index", "Admin", new { area = "Orchard.MediaLibrary" }); + + } + + public ActionResult Edit(int id) { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't edit media folder"))) + return new HttpUnauthorizedResult(); + + var folder = _mediaLibraryService.GetMediaFolder(id); + + var viewModel = new MediaManagerFolderEditViewModel { + Hierarchy = _mediaLibraryService.GetMediaFolderHierarchy(id), + FolderId = id, + Name = folder.Name + }; + + return View(viewModel); + } + + [HttpPost, ActionName("Edit")] + [FormValueRequired("submit.Save")] + public ActionResult Edit() { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't edit media folder"))) + return new HttpUnauthorizedResult(); + + var viewModel = new MediaManagerFolderEditViewModel(); + UpdateModel(viewModel); + + try { + _mediaLibraryService.RenameFolder(viewModel.FolderId, viewModel.Name); + Services.Notifier.Information(T("Media folder renamed")); + } + catch (ArgumentException argumentException) { + Services.Notifier.Error(T("Editing Folder failed: {0}", argumentException.Message)); + Services.TransactionManager.Cancel(); + return View(viewModel); + } + + return RedirectToAction("Index", "Admin", new { area = "Orchard.MediaLibrary" }); + } + + [HttpPost, ActionName("Edit")] + [FormValueRequired("submit.Delete")] + public ActionResult Delete() { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't delete media folder"))) + return new HttpUnauthorizedResult(); + + var viewModel = new MediaManagerFolderEditViewModel(); + UpdateModel(viewModel); + + try { + _mediaLibraryService.DeleteFolder(viewModel.FolderId); + Services.Notifier.Information(T("Media folder deleted")); + } + catch (ArgumentException argumentException) { + Services.Notifier.Error(T("Deleting Folder failed: {0}", argumentException.Message)); + Services.TransactionManager.Cancel(); + return View(viewModel); + } + + return RedirectToAction("Index", "Admin", new { area = "Orchard.MediaLibrary" }); + } + + [HttpPost] + public ActionResult Move(int targetId, int[] mediaItemIds) { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't move media items"))) + return new HttpUnauthorizedResult(); + + var targetFolder = _mediaLibraryService.GetMediaFolder(targetId); + + if (targetFolder == null) { + return Json(false); + } + + if (mediaItemIds == null || mediaItemIds.Length == 0) { + return Json(false); + } + + _mediaLibraryService.MoveMedia(targetId, mediaItemIds); + + return Json(true); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/WebSearchController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/WebSearchController.cs new file mode 100644 index 000000000..1c171136e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/WebSearchController.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Web; +using System.Web.Mvc; +using Orchard.MediaLibrary.Services; +using Orchard.Themes; +using Orchard.UI.Admin; + +namespace Orchard.MediaLibrary.Controllers { + [Admin, Themed(false)] + public class WebSearchController : Controller { + private readonly IMediaLibraryService _mediaLibraryService; + + public WebSearchController(IMediaLibraryService mediaManagerService) { + _mediaLibraryService = mediaManagerService; + } + + public ActionResult Index(int id) { + + return View(id); + } + + + [HttpPost] + public JsonResult ImagePost(int id, string url) { + + try { + var buffer = new WebClient().DownloadData(url); + var stream = new MemoryStream(buffer); + var mediaPart = _mediaLibraryService.ImportStream(id, stream, Path.GetFileName(url)); + + return new JsonResult { + Data = new {id, mediaPart.Resource} + }; + } + catch(Exception e) { + return new JsonResult { + Data = new { error= e.Message } + }; + } + + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs new file mode 100644 index 000000000..6c9381138 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs @@ -0,0 +1,15 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Drivers { + public class AudioPartDriver : ContentPartDriver { + protected override DriverResult Display(AudioPart part, string displayType, dynamic shapeHelper) { + return Combined( + ContentShape("Parts_Audio_Metadata", () => shapeHelper.Parts_Audio_Metadata()), + ContentShape("Parts_Audio_SummaryAdmin", () => shapeHelper.Parts_Audio_SummaryAdmin()), + ContentShape("Parts_Audio_Summary", () => shapeHelper.Parts_Audio_Summary()), + ContentShape("Parts_Audio", () => shapeHelper.Parts_Audio()) + ); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs new file mode 100644 index 000000000..690da95dc --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs @@ -0,0 +1,15 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Drivers { + public class DocumentPartDriver : ContentPartDriver { + protected override DriverResult Display(DocumentPart part, string displayType, dynamic shapeHelper) { + return Combined( + ContentShape("Parts_Document_Metadata", () => shapeHelper.Parts_Document_Metadata()), + ContentShape("Parts_Document_Summary", () => shapeHelper.Parts_Document_Summary()), + ContentShape("Parts_Document_SummaryAdmin", () => shapeHelper.Parts_Document_SummaryAdmin()), + ContentShape("Parts_Document", () => shapeHelper.Parts_Document()) + ); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs new file mode 100644 index 000000000..3256a2f72 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs @@ -0,0 +1,16 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Drivers { + public class ImagePartDriver : ContentPartDriver { + + protected override DriverResult Display(ImagePart part, string displayType, dynamic shapeHelper) { + return Combined( + ContentShape("Parts_Image_Metadata", () => shapeHelper.Parts_Image_Metadata()), + ContentShape("Parts_Image_Summary", () => shapeHelper.Parts_Image_Summary()), + ContentShape("Parts_Image", () => shapeHelper.Parts_Image()), + ContentShape("Parts_Image_SummaryAdmin", () => shapeHelper.Parts_Image_SummaryAdmin()) + ); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryPickerFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryPickerFieldDriver.cs new file mode 100644 index 000000000..8e1947b32 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryPickerFieldDriver.cs @@ -0,0 +1,101 @@ +using System; +using System.Linq; +using Orchard.MediaLibrary.Settings; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.Handlers; +using Orchard.MediaLibrary.ViewModels; +using Orchard.Localization; +using Orchard.Utility.Extensions; + +namespace Orchard.MediaLibrary.Drivers { + public class MediaLibraryPickerFieldDriver : ContentFieldDriver { + private readonly IContentManager _contentManager; + + public MediaLibraryPickerFieldDriver(IContentManager contentManager) { + _contentManager = contentManager; + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } + + private static string GetPrefix(Fields.MediaLibraryPickerField field, ContentPart part) { + return part.PartDefinition.Name + "." + field.Name; + } + + private static string GetDifferentiator(Fields.MediaLibraryPickerField field, ContentPart part) { + return field.Name; + } + + protected override DriverResult Display(ContentPart part, Fields.MediaLibraryPickerField field, string displayType, dynamic shapeHelper) { + return Combined( + ContentShape("Fields_MediaLibraryPicker", GetDifferentiator(field, part), () => shapeHelper.Fields_MediaLibraryPicker()), + ContentShape("Fields_MediaLibraryPicker_SummaryAdmin", GetDifferentiator(field, part), () => shapeHelper.Fields_MediaLibraryPicker_SummaryAdmin()) + ); + } + + protected override DriverResult Editor(ContentPart part, Fields.MediaLibraryPickerField field, dynamic shapeHelper) { + return ContentShape("Fields_MediaLibraryPicker_Edit", GetDifferentiator(field, part), + () => { + var model = new MediaLibraryPickerFieldViewModel { + Field = field, + Part = part, + ContentItems = _contentManager.GetMany(field.Ids, VersionOptions.Published, QueryHints.Empty).ToList(), + }; + + model.SelectedIds = string.Concat(",", field.Ids); + + return shapeHelper.EditorTemplate(TemplateName: "Fields/MediaLibraryPicker.Edit", Model: model, Prefix: GetPrefix(field, part)); + }); + } + + protected override DriverResult Editor(ContentPart part, Fields.MediaLibraryPickerField field, IUpdateModel updater, dynamic shapeHelper) { + var model = new MediaLibraryPickerFieldViewModel(); + + updater.TryUpdateModel(model, GetPrefix(field, part), null, null); + + var settings = field.PartFieldDefinition.Settings.GetModel(); + + if (String.IsNullOrEmpty(model.SelectedIds)) { + field.Ids = new int[0]; + } + else { + field.Ids = model.SelectedIds.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); + } + + if (settings.Required && field.Ids.Length == 0) { + updater.AddModelError("Id", T("The field {0} is mandatory", field.Name.CamelFriendly())); + } + + return Editor(part, field, shapeHelper); + } + + protected override void Importing(ContentPart part, Fields.MediaLibraryPickerField field, ImportContentContext context) { + var contentItemIds = context.Attribute(field.FieldDefinition.Name + "." + field.Name, "ContentItems"); + if (contentItemIds != null) { + field.Ids = contentItemIds.Split(',') + .Select(context.GetItemFromSession) + .Select(contentItem => contentItem.Id).ToArray(); + } + else { + field.Ids = new int[0]; + } + } + + protected override void Exporting(ContentPart part, Fields.MediaLibraryPickerField field, ExportContentContext context) { + if (field.Ids.Any()) { + var contentItemIds = field.Ids + .Select(x => _contentManager.Get(x)) + .Select(x => _contentManager.GetItemMetadata(x).Identity.ToString()) + .ToArray(); + + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("ContentItems", string.Join(",", contentItemIds)); + } + } + + protected override void Describe(DescribeMembersContext context) { + context + .Member(null, typeof(string), T("Ids"), T("A formatted list of the ids, e.g., {1},{42}")); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs new file mode 100644 index 000000000..6f7162d9f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs @@ -0,0 +1,22 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Drivers { + public class MediaPartDriver : ContentPartDriver { + protected override string Prefix { + get { return "MediaPart"; } + } + + protected override DriverResult Display(MediaPart part, string displayType, dynamic shapeHelper) { + return Combined( + ContentShape("Parts_Media_SummaryAdmin", () => shapeHelper.Parts_Media_SummaryAdmin()), + ContentShape("Parts_Media_Actions", () => shapeHelper.Parts_Media_Actions()) + ); + + } + + protected override DriverResult Editor(MediaPart part, dynamic shapeHelper) { + return ContentShape("Parts_Media_Edit", () => shapeHelper.EditorTemplate(TemplateName: "Parts.Media.Edit", Model: part, Prefix: Prefix)); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs new file mode 100644 index 000000000..afb7d99e6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs @@ -0,0 +1,15 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Drivers { + public class VideoPartDriver : ContentPartDriver { + protected override DriverResult Display(VideoPart part, string displayType, dynamic shapeHelper) { + return Combined( + ContentShape("Parts_Video_Metadata", () => shapeHelper.Parts_Video_Metadata()), + ContentShape("Parts_Video_SummaryAdmin", () => shapeHelper.Parts_Video_SummaryAdmin()), + ContentShape("Parts_Video_Summary", () => shapeHelper.Parts_Video_Summary()), + ContentShape("Parts_Video", () => shapeHelper.Parts_Video) + ); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/AudioFactory.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/AudioFactory.cs new file mode 100644 index 000000000..5e9ca8c65 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/AudioFactory.cs @@ -0,0 +1,66 @@ +using System.IO; +using Orchard.ContentManagement; +using Orchard.FileSystems.Media; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Factories { + + public class AudioFactorySelector : IMediaFactorySelector { + private readonly IContentManager _contentManager; + private readonly IStorageProvider _storageProvider; + + public AudioFactorySelector(IContentManager contentManager, IStorageProvider storageProvider) { + _contentManager = contentManager; + _storageProvider = storageProvider; + } + + public MediaFactorySelectorResult GetMediaFactory(Stream stream, string mimeType) { + if (!mimeType.StartsWith("audio/")) { + return null; + } + + return new MediaFactorySelectorResult { + Priority = -5, + MediaFactory = new AudioFactory(_contentManager, _storageProvider) + }; + + } + } + + public class AudioFactory : IMediaFactory { + private readonly IContentManager _contentManager; + private readonly IStorageProvider _storageProvider; + + public const string BaseFolder = "Audio"; + + public AudioFactory(IContentManager contentManager, IStorageProvider storageProvider) { + _contentManager = contentManager; + _storageProvider = storageProvider; + } + + public MediaPart CreateMedia(Stream stream, string path, string mimeType) { + var uniquePath = path; + var index = 1; + while (_storageProvider.FileExists(_storageProvider.Combine(BaseFolder, uniquePath))) { + uniquePath = Path.GetFileNameWithoutExtension(path) + "-" + index++ + Path.GetExtension(path); + } + + _storageProvider.SaveStream(_storageProvider.Combine(BaseFolder, uniquePath), stream); + + var part = _contentManager.New("Audio"); + + if (!_storageProvider.FolderExists(BaseFolder)) { + _storageProvider.CreateFolder(BaseFolder); + } + + part.Resource = _storageProvider.GetPublicUrl(_storageProvider.Combine(BaseFolder, uniquePath)); + part.MimeType = mimeType; + part.Title = Path.GetFileNameWithoutExtension(path); + + var audioPart = part.As(); + audioPart.Length = 0; + + return part; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/DocumentFactory.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/DocumentFactory.cs new file mode 100644 index 000000000..d6c634bd0 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/DocumentFactory.cs @@ -0,0 +1,65 @@ +using System.IO; +using Orchard.ContentManagement; +using Orchard.FileSystems.Media; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Factories { + + /// + /// The class is a fallback factory which create a Document media + /// if no other factory could handle the file. + /// + public class DocumentFactorySelector : IMediaFactorySelector { + private readonly IContentManager _contentManager; + private readonly IStorageProvider _storageProvider; + + public DocumentFactorySelector(IContentManager contentManager, IStorageProvider storageProvider) { + _contentManager = contentManager; + _storageProvider = storageProvider; + } + + public MediaFactorySelectorResult GetMediaFactory(Stream stream, string mimeType) { + return new MediaFactorySelectorResult { + Priority = -10, + MediaFactory = new DocumentFactory(_contentManager, _storageProvider) + }; + } + } + + public class DocumentFactory : IMediaFactory { + private readonly IContentManager _contentManager; + private readonly IStorageProvider _storageProvider; + + public const string BaseFolder = "Documents"; + + public DocumentFactory(IContentManager contentManager, IStorageProvider storageProvider) { + _contentManager = contentManager; + _storageProvider = storageProvider; + } + + public MediaPart CreateMedia(Stream stream, string path, string mimeType) { + var uniquePath = path; + var index = 1; + while (_storageProvider.FileExists(_storageProvider.Combine(BaseFolder, uniquePath))) { + uniquePath = Path.GetFileNameWithoutExtension(path) + "-" + index++ + Path.GetExtension(path); + } + + _storageProvider.SaveStream(_storageProvider.Combine(BaseFolder, uniquePath), stream); + + var part = _contentManager.New("Document"); + + if (!_storageProvider.FolderExists(BaseFolder)) { + _storageProvider.CreateFolder(BaseFolder); + } + + part.Resource = _storageProvider.GetPublicUrl(_storageProvider.Combine(BaseFolder, uniquePath)); + part.MimeType = mimeType; + part.Title = Path.GetFileNameWithoutExtension(path); + + var documentPart = part.As(); + documentPart.Length = stream.Length; + + return part; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/IMediaFactory.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/IMediaFactory.cs new file mode 100644 index 000000000..962c74fdd --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/IMediaFactory.cs @@ -0,0 +1,20 @@ +using System.IO; +using Orchard.ContentManagement; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Factories { + + public interface IMediaFactory { + MediaPart CreateMedia(Stream stream, string path, string mimeType); + } + + public class NullMediaFactory : IMediaFactory { + public static IMediaFactory Instance { + get { return new NullMediaFactory(); } + } + + public MediaPart CreateMedia(Stream stream, string path, string mimeType) { + return null; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/IMediaFactorySelector.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/IMediaFactorySelector.cs new file mode 100644 index 000000000..f21bfb276 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/IMediaFactorySelector.cs @@ -0,0 +1,7 @@ +using System.IO; + +namespace Orchard.MediaLibrary.Factories { + public interface IMediaFactorySelector : IDependency { + MediaFactorySelectorResult GetMediaFactory(Stream stream, string mimeType); + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/ImageFactory.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/ImageFactory.cs new file mode 100644 index 000000000..d16f7eadd --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/ImageFactory.cs @@ -0,0 +1,70 @@ +using System.Drawing; +using System.IO; +using Orchard.ContentManagement; +using Orchard.FileSystems.Media; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Factories { + + public class ImageFactorySelector : IMediaFactorySelector { + private readonly IContentManager _contentManager; + private readonly IStorageProvider _storageProvider; + + public ImageFactorySelector(IContentManager contentManager, IStorageProvider storageProvider) { + _contentManager = contentManager; + _storageProvider = storageProvider; + } + + public MediaFactorySelectorResult GetMediaFactory(Stream stream, string mimeType) { + if (!mimeType.StartsWith("image/")) { + return null; + } + + return new MediaFactorySelectorResult { + Priority = -5, + MediaFactory = new ImageFactory(_contentManager, _storageProvider) + }; + + } + } + + public class ImageFactory : IMediaFactory { + private readonly IContentManager _contentManager; + private readonly IStorageProvider _storageProvider; + + public const string BaseFolder = "Images"; + + public ImageFactory(IContentManager contentManager, IStorageProvider storageProvider) { + _contentManager = contentManager; + _storageProvider = storageProvider; + } + + public MediaPart CreateMedia(Stream stream, string path, string mimeType) { + var uniquePath = path; + var index = 1; + while (_storageProvider.FileExists(_storageProvider.Combine(BaseFolder, uniquePath))) { + uniquePath = Path.GetFileNameWithoutExtension(path) + "-" + index++ + Path.GetExtension(path); + } + + _storageProvider.SaveStream(_storageProvider.Combine(BaseFolder, uniquePath), stream); + + var part = _contentManager.New("Image"); + + if (!_storageProvider.FolderExists(BaseFolder)) { + _storageProvider.CreateFolder(BaseFolder); + } + + part.Resource = _storageProvider.GetPublicUrl(_storageProvider.Combine(BaseFolder, uniquePath)); + part.MimeType = mimeType; + part.Title = Path.GetFileNameWithoutExtension(path); + + var imagePart = part.As(); + using (var image = Image.FromStream(stream)) { + imagePart.Width = image.Width; + imagePart.Height = image.Height; + } + + return part; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/MediaFactorySelectorResult.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/MediaFactorySelectorResult.cs new file mode 100644 index 000000000..16b7ad25a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/MediaFactorySelectorResult.cs @@ -0,0 +1,6 @@ +namespace Orchard.MediaLibrary.Factories { + public class MediaFactorySelectorResult { + public int Priority { get; set; } + public IMediaFactory MediaFactory { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/VideoFactory.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/VideoFactory.cs new file mode 100644 index 000000000..213329893 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Factories/VideoFactory.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using Orchard.ContentManagement; +using Orchard.FileSystems.Media; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Factories { + + public class VideoFactorySelector : IMediaFactorySelector { + private readonly IContentManager _contentManager; + private readonly IStorageProvider _storageProvider; + + public VideoFactorySelector(IContentManager contentManager, IStorageProvider storageProvider) { + _contentManager = contentManager; + _storageProvider = storageProvider; + } + + public MediaFactorySelectorResult GetMediaFactory(Stream stream, string mimeType) { + if (!mimeType.StartsWith("video/")) { + return null; + } + + return new MediaFactorySelectorResult { + Priority = -5, + MediaFactory = new VideoFactory(_contentManager, _storageProvider) + }; + + } + } + + public class VideoFactory : IMediaFactory { + private readonly IContentManager _contentManager; + private readonly IStorageProvider _storageProvider; + + public const string BaseFolder = "Videos"; + + public VideoFactory(IContentManager contentManager, IStorageProvider storageProvider) { + _contentManager = contentManager; + _storageProvider = storageProvider; + } + + public MediaPart CreateMedia(Stream stream, string path, string mimeType) { + var uniquePath = path; + var index = 1; + while (_storageProvider.FileExists(_storageProvider.Combine(BaseFolder, uniquePath))) { + uniquePath = Path.GetFileNameWithoutExtension(path) + "-" + index++ + Path.GetExtension(path); + } + + _storageProvider.SaveStream(_storageProvider.Combine(BaseFolder, uniquePath), stream); + + var part = _contentManager.New("Video"); + + if (!_storageProvider.FolderExists(BaseFolder)) { + _storageProvider.CreateFolder(BaseFolder); + } + + part.Resource = _storageProvider.GetPublicUrl(_storageProvider.Combine(BaseFolder, uniquePath)); + part.MimeType = mimeType; + part.Title = Path.GetFileNameWithoutExtension(path); + + var videoPart = part.As(); + videoPart.Length = 0; + + return part; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Fields/MediaLibrayPickerField.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Fields/MediaLibrayPickerField.cs new file mode 100644 index 000000000..83a22d3b2 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Fields/MediaLibrayPickerField.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Orchard.ContentManagement; +using Orchard.ContentManagement.FieldStorage; +using Orchard.ContentManagement.Utilities; + +namespace Orchard.MediaLibrary.Fields { + public class MediaLibraryPickerField : ContentField { + private static readonly char[] separator = new [] {'{', '}', ','}; + internal LazyField> _contentItems = new LazyField>(); + + public int[] Ids { + get { return DecodeIds(Storage.Get()); } + set { Storage.Set(EncodeIds(value)); } + } + + public IEnumerable ContentItems { + get { + return _contentItems.Value; + } + } + + private string EncodeIds(ICollection ids) { + if (ids == null || !ids.Any()) { + return string.Empty; + } + + // use {1},{2} format so it can be filtered with delimiters + return "{" + string.Join("},{", ids.ToArray()) + "}"; + } + + private int[] DecodeIds(string ids) { + if(String.IsNullOrWhiteSpace(ids)) { + return new int[0]; + } + + return ids.Split(separator, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaLibraryPickerFieldHandler.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaLibraryPickerFieldHandler.cs new file mode 100644 index 000000000..961573cf6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaLibraryPickerFieldHandler.cs @@ -0,0 +1,37 @@ +using System.Linq; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Handlers; +using Orchard.ContentManagement.MetaData; +using Orchard.MediaLibrary.Fields; + +namespace Orchard.MediaLibrary.Handlers { + public class MediaLibraryPickerFieldHandler : ContentHandler { + private readonly IContentManager _contentManager; + private readonly IContentDefinitionManager _contentDefinitionManager; + + public MediaLibraryPickerFieldHandler( + IContentManager contentManager, + IContentDefinitionManager contentDefinitionManager) { + + _contentManager = contentManager; + _contentDefinitionManager = contentDefinitionManager; + } + + protected override void Loading(LoadContentContext context) { + base.Loading(context); + + var fields = context.ContentItem.Parts.SelectMany(x => x.Fields.Where(f => f.FieldDefinition.Name == typeof(MediaLibraryPickerField).Name)).Cast(); + + // define lazy initializer for ContentPickerField.ContentItems + var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(context.ContentType); + if (contentTypeDefinition == null) { + return; + } + + foreach (var field in fields) { + var localField = field; + field._contentItems.Loader(x => _contentManager.GetMany(localField.Ids, VersionOptions.Published, QueryHints.Empty)); + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs new file mode 100644 index 000000000..191174b21 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs @@ -0,0 +1,24 @@ +using Orchard.ContentManagement; +using Orchard.ContentManagement.Handlers; +using Orchard.Data; +using Orchard.MediaLibrary.Models; +using Orchard.Taxonomies.Models; + +namespace Orchard.MediaLibrary.Handlers { + public class MediaPartHandler : ContentHandler { + private readonly IContentManager _contentManager; + + public MediaPartHandler(IContentManager contentManager, IRepository repository) { + _contentManager = contentManager; + + Filters.Add(StorageFilter.For(repository)); + OnLoading((context, part) => LazyLoadHandlers(part)); + OnVersioning((context, part, newVersionPart) => LazyLoadHandlers(newVersionPart)); + } + + protected void LazyLoadHandlers(MediaPart part) { + // add handlers that will load content for id's just-in-time + part.TermPartField.Loader(() => part.Record.TermPartRecord == null ? null : _contentManager.Get(part.Record.TermPartRecord.Id)); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Migrations.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Migrations.cs new file mode 100644 index 000000000..ca7631b2a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Migrations.cs @@ -0,0 +1,71 @@ +using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData; +using Orchard.Data.Migration; +using Orchard.MediaLibrary.Services; +using Orchard.Taxonomies.Models; + +namespace Orchard.MediaLibrary { + public class MediaDataMigration : DataMigrationImpl { + private readonly IContentManager _contentManager; + + public MediaDataMigration(IContentManager contentManager) { + _contentManager = contentManager; + } + + public int Create() { + + SchemaBuilder.CreateTable("MediaPartRecord", t => t + .ContentPartRecord() + .Column("MimeType") + .Column("Caption", c => c.Unlimited()) + .Column("AlternateText", c => c.Unlimited()) + .Column("TermPartRecord_id") + .Column("Resource", c => c.WithLength(2048)) + ); + + var taxonomy = _contentManager.New("Taxonomy"); + taxonomy.IsInternal = true; + taxonomy.Name = MediaLibraryService.MediaLocation; + + _contentManager.Create(taxonomy); + + ContentDefinitionManager.AlterTypeDefinition("Image", td => td + .DisplayedAs("Image") + .WithSetting("Stereotype", "Media") + .WithPart("CommonPart") + .WithPart("MediaPart") + .WithPart("ImagePart") + .WithPart("TitlePart") + ); + + ContentDefinitionManager.AlterTypeDefinition("Video", td => td + .DisplayedAs("Video") + .WithSetting("Stereotype", "Media") + .WithPart("CommonPart") + .WithPart("MediaPart") + .WithPart("VideoPart") + .WithPart("TitlePart") + ); + + ContentDefinitionManager.AlterTypeDefinition("Audio", td => td + .DisplayedAs("Audio") + .WithSetting("Stereotype", "Media") + .WithPart("CommonPart") + .WithPart("MediaPart") + .WithPart("AudioPart") + .WithPart("TitlePart") + ); + + ContentDefinitionManager.AlterTypeDefinition("Document", td => td + .DisplayedAs("Document") + .WithSetting("Stereotype", "Media") + .WithPart("CommonPart") + .WithPart("MediaPart") + .WithPart("DocumentPart") + .WithPart("TitlePart") + ); + + return 1; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/AudioPart.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/AudioPart.cs new file mode 100644 index 000000000..7505dae52 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/AudioPart.cs @@ -0,0 +1,13 @@ +using System; +using System.Globalization; +using Orchard.ContentManagement; +using Orchard.ContentManagement.FieldStorage.InfosetStorage; + +namespace Orchard.MediaLibrary.Models { + public class AudioPart : ContentPart { + public int Length { + get { return Convert.ToInt32(this.As().Get("AudioPart", "Length", "Value"), CultureInfo.InvariantCulture); } + set { this.As().Set("AudioPart", "Length", "Value", Convert.ToString(value, CultureInfo.InvariantCulture)); } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/DocumentPart.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/DocumentPart.cs new file mode 100644 index 000000000..33735ec59 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/DocumentPart.cs @@ -0,0 +1,13 @@ +using System; +using System.Globalization; +using Orchard.ContentManagement; +using Orchard.ContentManagement.FieldStorage.InfosetStorage; + +namespace Orchard.MediaLibrary.Models { + public class DocumentPart : ContentPart { + public long Length { + get { return Convert.ToInt64(this.As().Get("DocumentPart", "Length", "Value"), CultureInfo.InvariantCulture); } + set { this.As().Set("DocumentPart", "Length", "Value", Convert.ToString(value, CultureInfo.InvariantCulture)); } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/ImagePart.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/ImagePart.cs new file mode 100644 index 000000000..90b69295d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/ImagePart.cs @@ -0,0 +1,19 @@ +using System; +using System.Globalization; +using Orchard.ContentManagement; +using Orchard.ContentManagement.FieldStorage.InfosetStorage; + +namespace Orchard.MediaLibrary.Models { + public class ImagePart : ContentPart { + + public int Width { + get { return Convert.ToInt32(this.As().Get("ImagePart", "Width", "Value"), CultureInfo.InvariantCulture); } + set { this.As().Set("ImagePart", "Width", "Value", Convert.ToString(value, CultureInfo.InvariantCulture)); } + } + + public int Height { + get { return Convert.ToInt32(this.As().Get("ImagePart", "Height", "Value"), CultureInfo.InvariantCulture); } + set { this.As().Set("ImagePart", "Height", "Value", Convert.ToString(value, CultureInfo.InvariantCulture)); } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaFolder.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaFolder.cs new file mode 100644 index 000000000..2cc3368c7 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaFolder.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Orchard.MediaLibrary.Models { + public class MediaFolder { + public MediaFolder() { + Folders = new List(); + } + + public string Name { get; set; } + public string MediaPath { get; set; } + public int TermId { get; set; } + public int? ParentTermId { get; set; } + + public IList Folders { get; set; } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPart.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPart.cs new file mode 100644 index 000000000..bac761dd5 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPart.cs @@ -0,0 +1,43 @@ +using Orchard.ContentManagement; +using Orchard.Core.Common.Utilities; +using Orchard.Core.Title.Models; +using Orchard.Taxonomies.Models; + +namespace Orchard.MediaLibrary.Models { + public class MediaPart : ContentPart { + + private readonly LazyField _termPartField = new LazyField(); + + public LazyField TermPartField { get { return _termPartField; } } + + public string Title { + get { return ContentItem.As().Title; } + set { ContentItem.As().Title = value; } + } + + public string MimeType { + get { return Record.MimeType; } + set { Record.MimeType = value; } + } + + public string Caption { + get { return Record.Caption; } + set { Record.Caption = value; } + } + + public string AlternateText { + get { return Record.AlternateText; } + set { Record.AlternateText = value; } + } + + public TermPart TermPart { + get { return _termPartField.Value; } + set { Record.TermPartRecord = value.Record; } + } + + public string Resource { + get { return Record.Resource; } + set { Record.Resource = value; } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPartRecord.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPartRecord.cs new file mode 100644 index 000000000..eafeb11ed --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPartRecord.cs @@ -0,0 +1,13 @@ +using Orchard.ContentManagement.Records; +using Orchard.Taxonomies.Models; + +namespace Orchard.MediaLibrary.Models { + public class MediaPartRecord : ContentPartRecord { + public virtual string MimeType { get; set; } + public virtual string Caption { get; set; } + public virtual string AlternateText { get; set; } + public virtual TermPartRecord TermPartRecord { get; set; } + public virtual string Resource { get; set; } + + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/VideoPart.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/VideoPart.cs new file mode 100644 index 000000000..400425294 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/VideoPart.cs @@ -0,0 +1,13 @@ +using System; +using System.Globalization; +using Orchard.ContentManagement; +using Orchard.ContentManagement.FieldStorage.InfosetStorage; + +namespace Orchard.MediaLibrary.Models { + public class VideoPart : ContentPart { + public int Length { + get { return Convert.ToInt32(this.As().Get("VideoPart", "Length", "Value"), CultureInfo.InvariantCulture); } + set { this.As().Set("VideoPart", "Length", "Value", Convert.ToString(value, CultureInfo.InvariantCulture)); } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt new file mode 100644 index 000000000..7eec6e331 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt @@ -0,0 +1,13 @@ +Name: Media Library +AntiForgery: enabled +Author: The Orchard Team +Website: http://orchardproject.net +Version: 1.0 +OrchardVersion: 1.0 +Description: Description for the module +Features: + Orchard.MediaLibrary: + Name: Media Library + Description: Description for feature Orchard.MediaLibrary. + Dependencies: Orchard.Taxonomies, Orchard.MediaProcessing, Title + Category: Media \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj new file mode 100644 index 000000000..8264c5dae --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj @@ -0,0 +1,326 @@ + + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {73A7688A-5BD3-4F7E-ADFA-CE36C5A10E3B} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Orchard.MediaLibrary + Orchard.MediaLibrary + v4.0 + false + + + 4.0 + + + false + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\ + TRACE + prompt + 4 + AllRules.ruleset + + + + + False + ..\..\..\..\lib\newtonsoft.json\Newtonsoft.Json.dll + + + + + 3.5 + + + + + False + ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} + Orchard.Framework + + + {9916839C-39FC-4CEB-A5AF-89CA7E87119F} + Orchard.Core + + + {08191fcd-7258-4f19-95fb-aec3de77b2eb} + Orchard.MediaProcessing + + + {E649EA64-D213-461B-87F7-D67035801443} + Orchard.Taxonomies + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + Styles\orchard-medialibrary-admin.css + + + + + + + + $(ProjectDir)\..\Manifests + + + + + + + + + + + + False + True + 45979 + / + + + False + True + http://orchard.codeplex.com + False + + + + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Permissions.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Permissions.cs new file mode 100644 index 000000000..3efd53f8e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Permissions.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using Orchard.Environment.Extensions.Models; +using Orchard.Security.Permissions; + +namespace Orchard.MediaLibrary { + public class Permissions : IPermissionProvider { + public static readonly Permission ManageMediaContent = new Permission { Description = "Managing Media", Name = "ManageMediaContent" }; + + public virtual Feature Feature { get; set; } + + public IEnumerable GetPermissions() { + return new[] { + ManageMediaContent, + }; + } + + public IEnumerable GetDefaultStereotypes() { + return new[] { + new PermissionStereotype { + Name = "Administrator", + Permissions = new[] {ManageMediaContent} + }, + new PermissionStereotype { + Name = "Editor", + Permissions = new[] {ManageMediaContent} + }, + new PermissionStereotype { + Name = "Moderator", + }, + new PermissionStereotype { + Name = "Author", + Permissions = new[] {ManageMediaContent} + }, + new PermissionStereotype { + Name = "Contributor", + }, + }; + } + + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Placement.info b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Placement.info new file mode 100644 index 000000000..2cd9ad91b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Placement.info @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..02547e413 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Orchard.MediaLibrary")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyProduct("Orchard")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f05ed81a-34d1-434c-945f-1ba8329ab1ff")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/ClientStorage/ClientStorageMenu.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/ClientStorage/ClientStorageMenu.cs new file mode 100644 index 000000000..1c3f83148 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/ClientStorage/ClientStorageMenu.cs @@ -0,0 +1,21 @@ +using Orchard.Localization; +using Orchard.UI.Navigation; + +namespace Orchard.MediaLibrary.Providers.ClientStorage { + public class NavigationProvider : INavigationProvider { + public Localizer T { get; set; } + + public NavigationProvider() { + T = NullLocalizer.Instance; + } + + public string MenuName { get { return "mediaproviders"; } } + + public void GetNavigation(NavigationBuilder builder) { + builder.AddImageSet("clientstorage") + .Add(T("My Computer"), "5", + menu => menu.Action("Index", "ClientStorage", new { area = "Orchard.MediaLibrary" }) + .Permission(Permissions.ManageMediaContent)); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/WebSearchMenu.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/WebSearchMenu.cs new file mode 100644 index 000000000..e698dfae6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Providers/WebSearchMenu.cs @@ -0,0 +1,21 @@ +using Orchard.Localization; +using Orchard.UI.Navigation; + +namespace Orchard.MediaLibrary.Providers { + public class WebSearchMenu : INavigationProvider { + public Localizer T { get; set; } + + public WebSearchMenu() { + T = NullLocalizer.Instance; + } + + public string MenuName { get { return "mediaproviders"; } } + + public void GetNavigation(NavigationBuilder builder) { + builder.AddImageSet("websearch") + .Add(T("Web Search"), "5", + menu => menu.Action("Index", "WebSearch", new { area = "Orchard.MediaLibrary" }) + .Permission(Permissions.ManageMediaContent)); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/ResourceManifest.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/ResourceManifest.cs new file mode 100644 index 000000000..2531d40d7 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/ResourceManifest.cs @@ -0,0 +1,9 @@ +using Orchard.UI.Resources; + +namespace Orchard.MediaLibrary { + public class ResourceManifest : IResourceManifestProvider { + public void BuildManifests(ResourceManifestBuilder builder) { + builder.Add().DefineStyle("MediaManagerAdmin").SetUrl("orchard-medialibrary-admin.css").SetDependencies("~/Themes/TheAdmin/Styles/Site.css"); + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/Web.config b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/Web.config new file mode 100644 index 000000000..770adfab5 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/Web.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/history.js b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/history.js new file mode 100644 index 000000000..4ff1d929a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/history.js @@ -0,0 +1 @@ +(function (a, b) { "use strict"; var c = a.console || b, d = a.document, e = a.navigator, f = a.sessionStorage || !1, g = a.setTimeout, h = a.clearTimeout, i = a.setInterval, j = a.clearInterval, k = a.JSON, l = a.alert, m = a.History = a.History || {}, n = a.history; k.stringify = k.stringify || k.encode, k.parse = k.parse || k.decode; if (typeof m.init != "undefined") throw new Error("History.js Core has already been loaded..."); m.init = function () { return typeof m.Adapter == "undefined" ? !1 : (typeof m.initCore != "undefined" && m.initCore(), typeof m.initHtml4 != "undefined" && m.initHtml4(), !0) }, m.initCore = function () { if (typeof m.initCore.initialized != "undefined") return !1; m.initCore.initialized = !0, m.options = m.options || {}, m.options.hashChangeInterval = m.options.hashChangeInterval || 100, m.options.safariPollInterval = m.options.safariPollInterval || 500, m.options.doubleCheckInterval = m.options.doubleCheckInterval || 500, m.options.storeInterval = m.options.storeInterval || 1e3, m.options.busyDelay = m.options.busyDelay || 250, m.options.debug = m.options.debug || !1, m.options.initialTitle = m.options.initialTitle || d.title, m.intervalList = [], m.clearAllIntervals = function () { var a, b = m.intervalList; if (typeof b != "undefined" && b !== null) { for (a = 0; a < b.length; a++) j(b[a]); m.intervalList = null } }, m.debug = function () { (m.options.debug || !1) && m.log.apply(m, arguments) }, m.log = function () { var a = typeof c != "undefined" && typeof c.log != "undefined" && typeof c.log.apply != "undefined", b = d.getElementById("log"), e, f, g, h, i; a ? (h = Array.prototype.slice.call(arguments), e = h.shift(), typeof c.debug != "undefined" ? c.debug.apply(c, [e, h]) : c.log.apply(c, [e, h])) : e = "\n" + arguments[0] + "\n"; for (f = 1, g = arguments.length; f < g; ++f) { i = arguments[f]; if (typeof i == "object" && typeof k != "undefined") try { i = k.stringify(i) } catch (j) { } e += "\n" + i + "\n" } return b ? (b.value += e + "\n-----\n", b.scrollTop = b.scrollHeight - b.clientHeight) : a || l(e), !0 }, m.getInternetExplorerMajorVersion = function () { var a = m.getInternetExplorerMajorVersion.cached = typeof m.getInternetExplorerMajorVersion.cached != "undefined" ? m.getInternetExplorerMajorVersion.cached : function () { var a = 3, b = d.createElement("div"), c = b.getElementsByTagName("i"); while ((b.innerHTML = "") && c[0]); return a > 4 ? a : !1 }(); return a }, m.isInternetExplorer = function () { var a = m.isInternetExplorer.cached = typeof m.isInternetExplorer.cached != "undefined" ? m.isInternetExplorer.cached : Boolean(m.getInternetExplorerMajorVersion()); return a }, m.emulated = { pushState: !Boolean(a.history && a.history.pushState && a.history.replaceState && !/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i.test(e.userAgent) && !/AppleWebKit\/5([0-2]|3[0-2])/i.test(e.userAgent)), hashChange: Boolean(!("onhashchange" in a || "onhashchange" in d) || m.isInternetExplorer() && m.getInternetExplorerMajorVersion() < 8) }, m.enabled = !m.emulated.pushState, m.bugs = { setHash: Boolean(!m.emulated.pushState && e.vendor === "Apple Computer, Inc." && /AppleWebKit\/5([0-2]|3[0-3])/.test(e.userAgent)), safariPoll: Boolean(!m.emulated.pushState && e.vendor === "Apple Computer, Inc." && /AppleWebKit\/5([0-2]|3[0-3])/.test(e.userAgent)), ieDoubleCheck: Boolean(m.isInternetExplorer() && m.getInternetExplorerMajorVersion() < 8), hashEscape: Boolean(m.isInternetExplorer() && m.getInternetExplorerMajorVersion() < 7) }, m.isEmptyObject = function (a) { for (var b in a) return !1; return !0 }, m.cloneObject = function (a) { var b, c; return a ? (b = k.stringify(a), c = k.parse(b)) : c = {}, c }, m.getRootUrl = function () { var a = d.location.protocol + "//" + (d.location.hostname || d.location.host); if (d.location.port || !1) a += ":" + d.location.port; return a += "/", a }, m.getBaseHref = function () { var a = d.getElementsByTagName("base"), b = null, c = ""; return a.length === 1 && (b = a[0], c = b.href.replace(/[^\/]+$/, "")), c = c.replace(/\/+$/, ""), c && (c += "/"), c }, m.getBaseUrl = function () { var a = m.getBaseHref() || m.getBasePageUrl() || m.getRootUrl(); return a }, m.getPageUrl = function () { var a = m.getState(!1, !1), b = (a || {}).url || d.location.href, c; return c = b.replace(/\/+$/, "").replace(/[^\/]+$/, function (a, b, c) { return /\./.test(a) ? a : a + "/" }), c }, m.getBasePageUrl = function () { var a = d.location.href.replace(/[#\?].*/, "").replace(/[^\/]+$/, function (a, b, c) { return /[^\/]$/.test(a) ? "" : a }).replace(/\/+$/, "") + "/"; return a }, m.getFullUrl = function (a, b) { var c = a, d = a.substring(0, 1); return b = typeof b == "undefined" ? !0 : b, /[a-z]+\:\/\//.test(a) || (d === "/" ? c = m.getRootUrl() + a.replace(/^\/+/, "") : d === "#" ? c = m.getPageUrl().replace(/#.*/, "") + a : d === "?" ? c = m.getPageUrl().replace(/[\?#].*/, "") + a : b ? c = m.getBaseUrl() + a.replace(/^(\.\/)+/, "") : c = m.getBasePageUrl() + a.replace(/^(\.\/)+/, "")), c.replace(/\#$/, "") }, m.getShortUrl = function (a) { var b = a, c = m.getBaseUrl(), d = m.getRootUrl(); return m.emulated.pushState && (b = b.replace(c, "")), b = b.replace(d, "/"), m.isTraditionalAnchor(b) && (b = "./" + b), b = b.replace(/^(\.\/)+/g, "./").replace(/\#$/, ""), b }, m.store = {}, m.idToState = m.idToState || {}, m.stateToId = m.stateToId || {}, m.urlToId = m.urlToId || {}, m.storedStates = m.storedStates || [], m.savedStates = m.savedStates || [], m.normalizeStore = function () { m.store.idToState = m.store.idToState || {}, m.store.urlToId = m.store.urlToId || {}, m.store.stateToId = m.store.stateToId || {} }, m.getState = function (a, b) { typeof a == "undefined" && (a = !0), typeof b == "undefined" && (b = !0); var c = m.getLastSavedState(); return !c && b && (c = m.createStateObject()), a && (c = m.cloneObject(c), c.url = c.cleanUrl || c.url), c }, m.getIdByState = function (a) { var b = m.extractId(a.url), c; if (!b) { c = m.getStateString(a); if (typeof m.stateToId[c] != "undefined") b = m.stateToId[c]; else if (typeof m.store.stateToId[c] != "undefined") b = m.store.stateToId[c]; else { for (; ;) { b = (new Date).getTime() + String(Math.random()).replace(/\D/g, ""); if (typeof m.idToState[b] == "undefined" && typeof m.store.idToState[b] == "undefined") break } m.stateToId[c] = b, m.idToState[b] = a } } return b }, m.normalizeState = function (a) { var b, c; if (!a || typeof a != "object") a = {}; if (typeof a.normalized != "undefined") return a; if (!a.data || typeof a.data != "object") a.data = {}; b = {}, b.normalized = !0, b.title = a.title || "", b.url = m.getFullUrl(m.unescapeString(a.url || d.location.href)), b.hash = m.getShortUrl(b.url), b.data = m.cloneObject(a.data), b.id = m.getIdByState(b), b.cleanUrl = b.url.replace(/\??\&_suid.*/, ""), b.url = b.cleanUrl, c = !m.isEmptyObject(b.data); if (b.title || c) b.hash = m.getShortUrl(b.url).replace(/\??\&_suid.*/, ""), /\?/.test(b.hash) || (b.hash += "?"), b.hash += "&_suid=" + b.id; return b.hashedUrl = m.getFullUrl(b.hash), (m.emulated.pushState || m.bugs.safariPoll) && m.hasUrlDuplicate(b) && (b.url = b.hashedUrl), b }, m.createStateObject = function (a, b, c) { var d = { data: a, title: b, url: c }; return d = m.normalizeState(d), d }, m.getStateById = function (a) { a = String(a); var c = m.idToState[a] || m.store.idToState[a] || b; return c }, m.getStateString = function (a) { var b, c, d; return b = m.normalizeState(a), c = { data: b.data, title: a.title, url: a.url }, d = k.stringify(c), d }, m.getStateId = function (a) { var b, c; return b = m.normalizeState(a), c = b.id, c }, m.getHashByState = function (a) { var b, c; return b = m.normalizeState(a), c = b.hash, c }, m.extractId = function (a) { var b, c, d; return c = /(.*)\&_suid=([0-9]+)$/.exec(a), d = c ? c[1] || a : a, b = c ? String(c[2] || "") : "", b || !1 }, m.isTraditionalAnchor = function (a) { var b = !/[\/\?\.]/.test(a); return b }, m.extractState = function (a, b) { var c = null, d, e; return b = b || !1, d = m.extractId(a), d && (c = m.getStateById(d)), c || (e = m.getFullUrl(a), d = m.getIdByUrl(e) || !1, d && (c = m.getStateById(d)), !c && b && !m.isTraditionalAnchor(a) && (c = m.createStateObject(null, null, e))), c }, m.getIdByUrl = function (a) { var c = m.urlToId[a] || m.store.urlToId[a] || b; return c }, m.getLastSavedState = function () { return m.savedStates[m.savedStates.length - 1] || b }, m.getLastStoredState = function () { return m.storedStates[m.storedStates.length - 1] || b }, m.hasUrlDuplicate = function (a) { var b = !1, c; return c = m.extractState(a.url), b = c && c.id !== a.id, b }, m.storeState = function (a) { return m.urlToId[a.url] = a.id, m.storedStates.push(m.cloneObject(a)), a }, m.isLastSavedState = function (a) { var b = !1, c, d, e; return m.savedStates.length && (c = a.id, d = m.getLastSavedState(), e = d.id, b = c === e), b }, m.saveState = function (a) { return m.isLastSavedState(a) ? !1 : (m.savedStates.push(m.cloneObject(a)), !0) }, m.getStateByIndex = function (a) { var b = null; return typeof a == "undefined" ? b = m.savedStates[m.savedStates.length - 1] : a < 0 ? b = m.savedStates[m.savedStates.length + a] : b = m.savedStates[a], b }, m.getHash = function () { var a = m.unescapeHash(d.location.hash); return a }, m.unescapeString = function (b) { var c = b, d; for (; ;) { d = a.unescape(c); if (d === c) break; c = d } return c }, m.unescapeHash = function (a) { var b = m.normalizeHash(a); return b = m.unescapeString(b), b }, m.normalizeHash = function (a) { var b = a.replace(/[^#]*#/, "").replace(/#.*/, ""); return b }, m.setHash = function (a, b) { var c, e, f; return b !== !1 && m.busy() ? (m.pushQueue({ scope: m, callback: m.setHash, args: arguments, queue: b }), !1) : (c = m.escapeHash(a), m.busy(!0), e = m.extractState(a, !0), e && !m.emulated.pushState ? m.pushState(e.data, e.title, e.url, !1) : d.location.hash !== c && (m.bugs.setHash ? (f = m.getPageUrl(), m.pushState(null, null, f + "#" + c, !1)) : d.location.hash = c), m) }, m.escapeHash = function (b) { var c = m.normalizeHash(b); return c = a.escape(c), m.bugs.hashEscape || (c = c.replace(/\%21/g, "!").replace(/\%26/g, "&").replace(/\%3D/g, "=").replace(/\%3F/g, "?")), c }, m.getHashByUrl = function (a) { var b = String(a).replace(/([^#]*)#?([^#]*)#?(.*)/, "$2"); return b = m.unescapeHash(b), b }, m.setTitle = function (a) { var b = a.title, c; b || (c = m.getStateByIndex(0), c && c.url === a.url && (b = c.title || m.options.initialTitle)); try { d.getElementsByTagName("title")[0].innerHTML = b.replace("<", "<").replace(">", ">").replace(" & ", " & ") } catch (e) { } return d.title = b, m }, m.queues = [], m.busy = function (a) { typeof a != "undefined" ? m.busy.flag = a : typeof m.busy.flag == "undefined" && (m.busy.flag = !1); if (!m.busy.flag) { h(m.busy.timeout); var b = function () { var a, c, d; if (m.busy.flag) return; for (a = m.queues.length - 1; a >= 0; --a) { c = m.queues[a]; if (c.length === 0) continue; d = c.shift(), m.fireQueueItem(d), m.busy.timeout = g(b, m.options.busyDelay) } }; m.busy.timeout = g(b, m.options.busyDelay) } return m.busy.flag }, m.busy.flag = !1, m.fireQueueItem = function (a) { return a.callback.apply(a.scope || m, a.args || []) }, m.pushQueue = function (a) { return m.queues[a.queue || 0] = m.queues[a.queue || 0] || [], m.queues[a.queue || 0].push(a), m }, m.queue = function (a, b) { return typeof a == "function" && (a = { callback: a }), typeof b != "undefined" && (a.queue = b), m.busy() ? m.pushQueue(a) : m.fireQueueItem(a), m }, m.clearQueue = function () { return m.busy.flag = !1, m.queues = [], m }, m.stateChanged = !1, m.doubleChecker = !1, m.doubleCheckComplete = function () { return m.stateChanged = !0, m.doubleCheckClear(), m }, m.doubleCheckClear = function () { return m.doubleChecker && (h(m.doubleChecker), m.doubleChecker = !1), m }, m.doubleCheck = function (a) { return m.stateChanged = !1, m.doubleCheckClear(), m.bugs.ieDoubleCheck && (m.doubleChecker = g(function () { return m.doubleCheckClear(), m.stateChanged || a(), !0 }, m.options.doubleCheckInterval)), m }, m.safariStatePoll = function () { var b = m.extractState(d.location.href), c; if (!m.isLastSavedState(b)) c = b; else return; return c || (c = m.createStateObject()), m.Adapter.trigger(a, "popstate"), m }, m.back = function (a) { return a !== !1 && m.busy() ? (m.pushQueue({ scope: m, callback: m.back, args: arguments, queue: a }), !1) : (m.busy(!0), m.doubleCheck(function () { m.back(!1) }), n.go(-1), !0) }, m.forward = function (a) { return a !== !1 && m.busy() ? (m.pushQueue({ scope: m, callback: m.forward, args: arguments, queue: a }), !1) : (m.busy(!0), m.doubleCheck(function () { m.forward(!1) }), n.go(1), !0) }, m.go = function (a, b) { var c; if (a > 0) for (c = 1; c <= a; ++c) m.forward(b); else { if (!(a < 0)) throw new Error("History.go: History.go requires a positive or negative integer passed."); for (c = -1; c >= a; --c) m.back(b) } return m }; if (m.emulated.pushState) { var o = function () { }; m.pushState = m.pushState || o, m.replaceState = m.replaceState || o } else m.onPopState = function (b, c) { var e = !1, f = !1, g, h; return m.doubleCheckComplete(), g = m.getHash(), g ? (h = m.extractState(g || d.location.href, !0), h ? m.replaceState(h.data, h.title, h.url, !1) : (m.Adapter.trigger(a, "anchorchange"), m.busy(!1)), m.expectedStateId = !1, !1) : (e = m.Adapter.extractEventData("state", b, c) || !1, e ? f = m.getStateById(e) : m.expectedStateId ? f = m.getStateById(m.expectedStateId) : f = m.extractState(d.location.href), f || (f = m.createStateObject(null, null, d.location.href)), m.expectedStateId = !1, m.isLastSavedState(f) ? (m.busy(!1), !1) : (m.storeState(f), m.saveState(f), m.setTitle(f), m.Adapter.trigger(a, "statechange"), m.busy(!1), !0)) }, m.Adapter.bind(a, "popstate", m.onPopState), m.pushState = function (b, c, d, e) { if (m.getHashByUrl(d) && m.emulated.pushState) throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors)."); if (e !== !1 && m.busy()) return m.pushQueue({ scope: m, callback: m.pushState, args: arguments, queue: e }), !1; m.busy(!0); var f = m.createStateObject(b, c, d); return m.isLastSavedState(f) ? m.busy(!1) : (m.storeState(f), m.expectedStateId = f.id, n.pushState(f.id, f.title, f.url), m.Adapter.trigger(a, "popstate")), !0 }, m.replaceState = function (b, c, d, e) { if (m.getHashByUrl(d) && m.emulated.pushState) throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors)."); if (e !== !1 && m.busy()) return m.pushQueue({ scope: m, callback: m.replaceState, args: arguments, queue: e }), !1; m.busy(!0); var f = m.createStateObject(b, c, d); return m.isLastSavedState(f) ? m.busy(!1) : (m.storeState(f), m.expectedStateId = f.id, n.replaceState(f.id, f.title, f.url), m.Adapter.trigger(a, "popstate")), !0 }; if (f) { try { m.store = k.parse(f.getItem("History.store")) || {} } catch (p) { m.store = {} } m.normalizeStore() } else m.store = {}, m.normalizeStore(); m.Adapter.bind(a, "beforeunload", m.clearAllIntervals), m.Adapter.bind(a, "unload", m.clearAllIntervals), m.saveState(m.storeState(m.extractState(d.location.href, !0))), f && (m.onUnload = function () { var a, b; try { a = k.parse(f.getItem("History.store")) || {} } catch (c) { a = {} } a.idToState = a.idToState || {}, a.urlToId = a.urlToId || {}, a.stateToId = a.stateToId || {}; for (b in m.idToState) { if (!m.idToState.hasOwnProperty(b)) continue; a.idToState[b] = m.idToState[b] } for (b in m.urlToId) { if (!m.urlToId.hasOwnProperty(b)) continue; a.urlToId[b] = m.urlToId[b] } for (b in m.stateToId) { if (!m.stateToId.hasOwnProperty(b)) continue; a.stateToId[b] = m.stateToId[b] } m.store = a, m.normalizeStore(), f.setItem("History.store", k.stringify(a)) }, m.intervalList.push(i(m.onUnload, m.options.storeInterval)), m.Adapter.bind(a, "beforeunload", m.onUnload), m.Adapter.bind(a, "unload", m.onUnload)); if (!m.emulated.pushState) { m.bugs.safariPoll && m.intervalList.push(i(m.safariStatePoll, m.options.safariPollInterval)); if (e.vendor === "Apple Computer, Inc." || (e.appCodeName || "") === "Mozilla") m.Adapter.bind(a, "hashchange", function () { m.Adapter.trigger(a, "popstate") }), m.getHash() && m.Adapter.onDomLoad(function () { m.Adapter.trigger(a, "hashchange") }) } }, m.init() })(window) \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/knockout-2.2.1.js b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/knockout-2.2.1.js new file mode 100644 index 000000000..d93e4977c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/knockout-2.2.1.js @@ -0,0 +1,85 @@ +// Knockout JavaScript library v2.2.1 +// (c) Steven Sanderson - http://knockoutjs.com/ +// License: MIT (http://www.opensource.org/licenses/mit-license.php) + +(function() {function j(w){throw w;}var m=!0,p=null,r=!1;function u(w){return function(){return w}};var x=window,y=document,ga=navigator,F=window.jQuery,I=void 0; +function L(w){function ha(a,d,c,e,f){var g=[];a=b.j(function(){var a=d(c,f)||[];0b.a.i(d,a[c])&&d.push(a[c]);return d},V:function(a,b){a=a||[];for(var d=[],c=0,e=a.length;cn?a.setAttribute("selected",b):a.selected=b},D:function(a){return(a||"").replace(d,"")},Rb:function(a,d){for(var c=[],e=(a||"").split(d),f=0,g=e.length;fa.length?r:a.substring(0,b.length)===b},tb:function(a,b){if(b.compareDocumentPosition)return 16== +(b.compareDocumentPosition(a)&16);for(;a!=p;){if(a==b)return m;a=a.parentNode}return r},X:function(a){return b.a.tb(a,a.ownerDocument)},u:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},n:function(b,d,c){var e=n&&l[d];if(!e&&"undefined"!=typeof F){if(a(b,d)){var f=c;c=function(a,b){var d=this.checked;b&&(this.checked=b.nb!==m);f.call(this,a);this.checked=d}}F(b).bind(d,c)}else!e&&"function"==typeof b.addEventListener?b.addEventListener(d,c,r):"undefined"!=typeof b.attachEvent?b.attachEvent("on"+ +d,function(a){c.call(b,a)}):j(Error("Browser doesn't support addEventListener or attachEvent"))},Ba:function(b,d){(!b||!b.nodeType)&&j(Error("element must be a DOM node when calling triggerEvent"));if("undefined"!=typeof F){var c=[];a(b,d)&&c.push({nb:b.checked});F(b).trigger(d,c)}else"function"==typeof y.createEvent?"function"==typeof b.dispatchEvent?(c=y.createEvent(e[d]||"HTMLEvents"),c.initEvent(d,m,m,x,0,0,0,0,0,r,r,r,r,0,b),b.dispatchEvent(c)):j(Error("The supplied element doesn't support dispatchEvent")): +"undefined"!=typeof b.fireEvent?(a(b,d)&&(b.checked=b.checked!==m),b.fireEvent("on"+d)):j(Error("Browser doesn't support triggering events"))},d:function(a){return b.$(a)?a():a},ua:function(a){return b.$(a)?a.t():a},da:function(a,d,c){if(d){var e=/[\w-]+/g,f=a.className.match(e)||[];b.a.o(d.match(e),function(a){var d=b.a.i(f,a);0<=d?c||f.splice(d,1):c&&f.push(a)});a.className=f.join(" ")}},cb:function(a,d){var c=b.a.d(d);if(c===p||c===I)c="";if(3===a.nodeType)a.data=c;else{var e=b.e.firstChild(a); +!e||3!=e.nodeType||b.e.nextSibling(e)?b.e.N(a,[y.createTextNode(c)]):e.data=c;b.a.wb(a)}},ab:function(a,b){a.name=b;if(7>=n)try{a.mergeAttributes(y.createElement(""),r)}catch(d){}},wb:function(a){9<=n&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},ub:function(a){if(9<=n){var b=a.style.width;a.style.width=0;a.style.width=b}},Lb:function(a,d){a=b.a.d(a);d=b.a.d(d);for(var c=[],e=a;e<=d;e++)c.push(e);return c},L:function(a){for(var b=[],d=0,c=a.length;d< +c;d++)b.push(a[d]);return b},Pb:6===n,Qb:7===n,Z:n,Oa:function(a,d){for(var c=b.a.L(a.getElementsByTagName("input")).concat(b.a.L(a.getElementsByTagName("textarea"))),e="string"==typeof d?function(a){return a.name===d}:function(a){return d.test(a.name)},f=[],g=c.length-1;0<=g;g--)e(c[g])&&f.push(c[g]);return f},Ib:function(a){return"string"==typeof a&&(a=b.a.D(a))?x.JSON&&x.JSON.parse?x.JSON.parse(a):(new Function("return "+a))():p},xa:function(a,d,c){("undefined"==typeof JSON||"undefined"==typeof JSON.stringify)&& +j(Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js"));return JSON.stringify(b.a.d(a),d,c)},Jb:function(a,d,c){c=c||{};var e=c.params||{},f=c.includeFields||this.Na,g=a;if("object"==typeof a&&"form"===b.a.u(a))for(var g=a.action,h=f.length-1;0<=h;h--)for(var k=b.a.Oa(a,f[h]),l=k.length-1;0<=l;l--)e[k[l].name]=k[l].value;d=b.a.d(d);var n=y.createElement("form"); +n.style.display="none";n.action=g;n.method="post";for(var w in d)a=y.createElement("input"),a.name=w,a.value=b.a.xa(b.a.d(d[w])),n.appendChild(a);for(w in e)a=y.createElement("input"),a.name=w,a.value=e[w],n.appendChild(a);y.body.appendChild(n);c.submitter?c.submitter(n):n.submit();setTimeout(function(){n.parentNode.removeChild(n)},0)}}};b.b("utils",b.a);b.b("utils.arrayForEach",b.a.o);b.b("utils.arrayFirst",b.a.lb);b.b("utils.arrayFilter",b.a.fa);b.b("utils.arrayGetDistinctValues",b.a.Ga);b.b("utils.arrayIndexOf", +b.a.i);b.b("utils.arrayMap",b.a.V);b.b("utils.arrayPushAll",b.a.P);b.b("utils.arrayRemoveItem",b.a.ga);b.b("utils.extend",b.a.extend);b.b("utils.fieldsIncludedWithJsonPost",b.a.Na);b.b("utils.getFormFields",b.a.Oa);b.b("utils.peekObservable",b.a.ua);b.b("utils.postJson",b.a.Jb);b.b("utils.parseJson",b.a.Ib);b.b("utils.registerEventHandler",b.a.n);b.b("utils.stringifyJson",b.a.xa);b.b("utils.range",b.a.Lb);b.b("utils.toggleDomNodeCssClass",b.a.da);b.b("utils.triggerEvent",b.a.Ba);b.b("utils.unwrapObservable", +b.a.d);Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice.call(arguments);a=c.shift();return function(){return b.apply(a,c.concat(Array.prototype.slice.call(arguments)))}});b.a.f=new function(){var a=0,d="__ko__"+(new Date).getTime(),c={};return{get:function(a,d){var c=b.a.f.la(a,r);return c===I?I:c[d]},set:function(a,d,c){c===I&&b.a.f.la(a,r)===I||(b.a.f.la(a,m)[d]=c)},la:function(b,f){var g=b[d];if(!g||!("null"!==g&&c[g])){if(!f)return I;g=b[d]="ko"+ +a++;c[g]={}}return c[g]},clear:function(a){var b=a[d];return b?(delete c[b],a[d]=p,m):r}}};b.b("utils.domData",b.a.f);b.b("utils.domData.clear",b.a.f.clear);b.a.F=new function(){function a(a,d){var e=b.a.f.get(a,c);e===I&&d&&(e=[],b.a.f.set(a,c,e));return e}function d(c){var e=a(c,r);if(e)for(var e=e.slice(0),k=0;k",""]||!c.indexOf("",""]||(!c.indexOf("",""]||[0,"",""];a="ignored
"+c[1]+a+c[2]+"
";for("function"==typeof x.innerShiv?d.appendChild(x.innerShiv(a)):d.innerHTML=a;c[0]--;)d=d.lastChild;d=b.a.L(d.lastChild.childNodes)}return d};b.a.ca=function(a,d){b.a.ka(a);d=b.a.d(d);if(d!==p&&d!==I)if("string"!=typeof d&&(d=d.toString()), +"undefined"!=typeof F)F(a).html(d);else for(var c=b.a.ta(d),e=0;ec;c++)a=a();return a})};b.toJSON=function(a,d,c){a=b.gb(a);return b.a.xa(a,d,c)};b.b("toJS",b.gb);b.b("toJSON",b.toJSON);b.k={q:function(a){switch(b.a.u(a)){case "option":return a.__ko__hasDomDataOptionValue__=== +m?b.a.f.get(a,b.c.options.sa):7>=b.a.Z?a.getAttributeNode("value").specified?a.value:a.text:a.value;case "select":return 0<=a.selectedIndex?b.k.q(a.options[a.selectedIndex]):I;default:return a.value}},T:function(a,d){switch(b.a.u(a)){case "option":switch(typeof d){case "string":b.a.f.set(a,b.c.options.sa,I);"__ko__hasDomDataOptionValue__"in a&&delete a.__ko__hasDomDataOptionValue__;a.value=d;break;default:b.a.f.set(a,b.c.options.sa,d),a.__ko__hasDomDataOptionValue__=m,a.value="number"===typeof d? +d:""}break;case "select":for(var c=a.options.length-1;0<=c;c--)if(b.k.q(a.options[c])==d){a.selectedIndex=c;break}break;default:if(d===p||d===I)d="";a.value=d}}};b.b("selectExtensions",b.k);b.b("selectExtensions.readValue",b.k.q);b.b("selectExtensions.writeValue",b.k.T);var ka=/\@ko_token_(\d+)\@/g,na=["true","false"],oa=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;b.g={Q:[],aa:function(a){var d=b.a.D(a);if(3>d.length)return[];"{"===d.charAt(0)&&(d=d.substring(1,d.length-1));a=[];for(var c= +p,e,f=0;f=b.a.Z&&e in fa?(e=fa[e],g?a.removeAttribute(e): +a[e]=f):g||a.setAttribute(e,f.toString());"name"===e&&b.a.ab(a,g?"":f.toString())}}};b.c.checked={init:function(a,d,c){b.a.n(a,"click",function(){var e;if("checkbox"==a.type)e=a.checked;else if("radio"==a.type&&a.checked)e=a.value;else return;var f=d(),g=b.a.d(f);"checkbox"==a.type&&g instanceof Array?(e=b.a.i(g,a.value),a.checked&&0>e?f.push(a.value):!a.checked&&0<=e&&f.splice(e,1)):b.g.ea(f,c,"checked",e,m)});"radio"==a.type&&!a.name&&b.c.uniqueName.init(a,u(m))},update:function(a,d){var c=b.a.d(d()); +"checkbox"==a.type?a.checked=c instanceof Array?0<=b.a.i(c,a.value):c:"radio"==a.type&&(a.checked=a.value==c)}};b.c.css={update:function(a,d){var c=b.a.d(d());if("object"==typeof c)for(var e in c){var f=b.a.d(c[e]);b.a.da(a,e,f)}else c=String(c||""),b.a.da(a,a.__ko__cssValue,r),a.__ko__cssValue=c,b.a.da(a,c,m)}};b.c.enable={update:function(a,d){var c=b.a.d(d());c&&a.disabled?a.removeAttribute("disabled"):!c&&!a.disabled&&(a.disabled=m)}};b.c.disable={update:function(a,d){b.c.enable.update(a,function(){return!b.a.d(d())})}}; +b.c.event={init:function(a,d,c,e){var f=d()||{},g;for(g in f)(function(){var f=g;"string"==typeof f&&b.a.n(a,f,function(a){var g,n=d()[f];if(n){var q=c();try{var s=b.a.L(arguments);s.unshift(e);g=n.apply(e,s)}finally{g!==m&&(a.preventDefault?a.preventDefault():a.returnValue=r)}q[f+"Bubble"]===r&&(a.cancelBubble=m,a.stopPropagation&&a.stopPropagation())}})})()}};b.c.foreach={Sa:function(a){return function(){var d=a(),c=b.a.ua(d);if(!c||"number"==typeof c.length)return{foreach:d,templateEngine:b.C.oa}; +b.a.d(d);return{foreach:c.data,as:c.as,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRender:c.afterRender,beforeMove:c.beforeMove,afterMove:c.afterMove,templateEngine:b.C.oa}}},init:function(a,d){return b.c.template.init(a,b.c.foreach.Sa(d))},update:function(a,d,c,e,f){return b.c.template.update(a,b.c.foreach.Sa(d),c,e,f)}};b.g.Q.foreach=r;b.e.I.foreach=m;b.c.hasfocus={init:function(a,d,c){function e(e){a.__ko_hasfocusUpdating=m;var f=a.ownerDocument;"activeElement"in +f&&(e=f.activeElement===a);f=d();b.g.ea(f,c,"hasfocus",e,m);a.__ko_hasfocusUpdating=r}var f=e.bind(p,m),g=e.bind(p,r);b.a.n(a,"focus",f);b.a.n(a,"focusin",f);b.a.n(a,"blur",g);b.a.n(a,"focusout",g)},update:function(a,d){var c=b.a.d(d());a.__ko_hasfocusUpdating||(c?a.focus():a.blur(),b.r.K(b.a.Ba,p,[a,c?"focusin":"focusout"]))}};b.c.html={init:function(){return{controlsDescendantBindings:m}},update:function(a,d){b.a.ca(a,d())}};var da="__ko_withIfBindingData";Q("if");Q("ifnot",r,m);Q("with",m,r,function(a, +b){return a.createChildContext(b)});b.c.options={update:function(a,d,c){"select"!==b.a.u(a)&&j(Error("options binding applies only to SELECT elements"));for(var e=0==a.length,f=b.a.V(b.a.fa(a.childNodes,function(a){return a.tagName&&"option"===b.a.u(a)&&a.selected}),function(a){return b.k.q(a)||a.innerText||a.textContent}),g=a.scrollTop,h=b.a.d(d());0b.a.Z)&&a.nodes?a.nodes():p;if(d)return b.a.L(d.cloneNode(m).childNodes);a=a.text();return b.a.ta(a)};b.C.oa=new b.C;b.wa(b.C.oa);b.b("nativeTemplateEngine",b.C);b.qa=function(){var a=this.Db=function(){if("undefined"==typeof F||!F.tmpl)return 0;try{if(0<=F.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,c,e){e=e||{};2>a&&j(Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.")); +var f=b.data("precompiled");f||(f=b.text()||"",f=F.template(p,"{{ko_with $item.koBindingContext}}"+f+"{{/ko_with}}"),b.data("precompiled",f));b=[c.$data];c=F.extend({koBindingContext:c},e.templateOptions);c=F.tmpl(f,b,c);c.appendTo(y.createElement("div"));F.fragments={};return c};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){y.write(" +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml new file mode 100644 index 000000000..4cffee787 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml @@ -0,0 +1,403 @@ +@model Orchard.MediaLibrary.ViewModels.MediaManagerIndexViewModel + +@{ + var viewModel = Model; + + Script.Require("ShapesBase"); + Style.Require("MediaManagerAdmin"); + Script.Require("jQuery"); + Script.Require("jQueryUI_Droppable"); + Script.Include("knockout-2.2.1.js"); + Script.Include("history.js"); + + if (Model.DialogMode) { + Style.Include("dialog-mode.css"); + } + + Layout.Title = T("Media Library"); +} + +
+ +
+
+
    +
  • +

    @T("Categories")

    + +
      + @foreach (var folder in viewModel.Folders) { +
    • + @Display.Partial(TemplateName: "MediaManagerFolder", Model: folder) +
    • + } +
    + +
  • +
  • @T("Recent")

  • +
  • @T("Starred")

  • +
+
+
+
+
    +
  • +
    +
    +
    +

    +
    +
  • +
+
+
+
+
+

@T("PROPERTIES")

+
+ +
+
+
+
+
+

@T("SELECTION")

+
    +
  • +
    +
    +
  • +
+
+
+
+
+ + +
+
+
+
+
+
+ + + @using(Script.Foot()) { + + } diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaItems.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaItems.cshtml new file mode 100644 index 000000000..3a9eeb29b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaItems.cshtml @@ -0,0 +1,24 @@ +@using Orchard.Utility.Extensions +@model Orchard.MediaLibrary.ViewModels.MediaManagerMediaItemsViewModel +@{ + Response.ContentType = "text/json"; + @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject( + new { + mediaItemsCount = Model.MediaItemsCount, + mediaItems = Model.MediaItems.Select(x => new { + id = x.MediaPart.Id, + contentType = x.MediaPart.ContentItem.ContentType, + contentTypeClass = x.MediaPart.ContentItem.ContentType.HtmlClassify(), + title = x.MediaPart.Title, + alternateText = x.MediaPart.AlternateText, + caption = x.MediaPart.Caption, + resource = x.MediaPart.Resource, + mimeType = x.MediaPart.MimeType, + mimeTypeClass = x.MediaPart.MimeType.HtmlClassify(), + thumbnail = Display(x.Shape).ToString(), + editLink = Url.ItemEditUrl(x.MediaPart) + }).ToArray() + })) +} + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaManagerFolder.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaManagerFolder.cshtml new file mode 100644 index 000000000..7c138ae01 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaManagerFolder.cshtml @@ -0,0 +1,17 @@ +@model Orchard.MediaLibrary.Models.MediaFolder + +
+
+   + @Model.Name +
+ @if (Model.Folders.Any()) { +
    + @foreach (var folder in Model.Folders) { +
  • + @Display.Partial(TemplateName: "MediaManagerFolder", Model: folder) +
  • + } +
+ } +
diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/ClientStorage/Index.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/ClientStorage/Index.cshtml new file mode 100644 index 000000000..bc72aebfb --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/ClientStorage/Index.cshtml @@ -0,0 +1,151 @@ +@using System.Text + + + + + @{ + Script.Require("jQuery"); + Script.Require("jQueryUI"); + + Style.Include("orchard-medialibrary-admin.css"); + Style.Include("orchard-mediaproviders-admin.css"); + Style.Include("orchard-clientstorage-admin.css"); + + Script.Require("jQueryFileUpload"); + Script.Include("knockout-2.2.1.js"); + } + + @Display.Metas() + @Display.HeadScripts() + @Display.HeadLinks() + @Display.StyleSheetLinks() + + + +
+
@T("Click here, Drop files or Paste images")
+
+ +
    +
  • +
    +
    + +
    +
    +
    +
  • +
+ +
+ +
+ + + @using(Script.Foot()) { + + } + + @Display.FootScripts() + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/DefinitionTemplates/MediaLibraryPickerFieldSettings.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/DefinitionTemplates/MediaLibraryPickerFieldSettings.cshtml new file mode 100644 index 000000000..589264b0d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/DefinitionTemplates/MediaLibraryPickerFieldSettings.cshtml @@ -0,0 +1,27 @@ +@model Orchard.MediaLibrary.Settings.MediaLibraryPickerFieldSettings + +
+
+ @Html.CheckBoxFor(m => m.Required) + @T("Check to ensure the user is providing at least one media item.") +
+
+
+
+ @Html.CheckBoxFor(m => m.Multiple) + @T("Check to allow the user to select multiple media items.") +
+
+
+ + @Html.TextAreaFor(m => m.Hint, new { @class = "textMedium", rows = "5" } ) + @T("The help text is written under the field when authors are selecting media items.") + @Html.ValidationMessageFor(m => m.Hint) +
+
+
+ + @Html.TextBoxFor(m => m.DisplayedContentTypes) + @T("A comma separated value of all the content types or content parts to display.") +
+
diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Fields/MediaLibraryPicker.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Fields/MediaLibraryPicker.Edit.cshtml new file mode 100644 index 000000000..be1040c55 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Fields/MediaLibraryPicker.Edit.cshtml @@ -0,0 +1,129 @@ +@model Orchard.MediaLibrary.ViewModels.MediaLibraryPickerFieldViewModel +@using Orchard.ContentManagement +@using Orchard.Utility.Extensions; +@using Orchard.MediaLibrary.Settings; + +@{ + Script.Require("jQueryUI_Sortable").AtFoot(); + Style.Include("media-library-picker-admin.css"); + + Script.Require("jQueryColorBox"); + Style.Require("jQueryColorBox"); + + var settings = Model.Field.PartFieldDefinition.Settings.GetModel(); + var contentManager = WorkContext.Resolve(); +} + +
+ +
@T("You need to save your changes.")
+
+
    + @foreach (var contentItem in Model.ContentItems) { +
  • +
    +
    + @Display(contentManager.BuildDisplay(contentItem, "Thumbnail")) +
    +

    @Html.ItemDisplayText(contentItem)

    +
    + +
    +
    + @T("Remove") +
  • + } +
+
+ +
+ @T("Add") +
+ + @Html.HiddenFor(m => m.SelectedIds) + @settings.Hint +
+ +@using (Script.Foot()) { + +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Parts.Media.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Parts.Media.Edit.cshtml new file mode 100644 index 000000000..0d5366e47 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Parts.Media.Edit.cshtml @@ -0,0 +1,13 @@ +@model Orchard.MediaLibrary.Models.MediaPart + +
+ @Html.LabelFor(m => m.Caption, T("Caption")) + @Html.TextAreaFor(m => m.Caption, new { @class = "large text"}) + @T("The caption describes the image in a general context.") +
+ +
+ @Html.LabelFor(m => m.Caption, T("Alternate Text")) + @Html.TextBoxFor(m => m.Caption, new { @class = "large text"}) + @T("The alternate text is used when the media can't be rendered in a browser.") +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Fields/MediaLibraryPicker.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Fields/MediaLibraryPicker.SummaryAdmin.cshtml new file mode 100644 index 000000000..120df48f9 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Fields/MediaLibraryPicker.SummaryAdmin.cshtml @@ -0,0 +1,33 @@ +@using Orchard.Core.Contents +@using Orchard.MediaLibrary.Fields +@using Orchard.Utility.Extensions; + +@{ + var field = (MediaLibraryPickerField) Model.ContentField; + string name = field.DisplayName; + var contentItems = field.ContentItems; + + var returnUrl = ViewContext.RequestContext.HttpContext.Request.ToUrlString(); +} +@name: +

+ + @if(contentItems.Any()) { + foreach(var contentItem in contentItems) { + + @if (Authorizer.Authorize(Permissions.EditContent, contentItem)) { + + @Display(BuildDisplay(contentItem, "Thumbnail")) + + } + else { + @Display(BuildDisplay(contentItem, "Thumbnail")) + } + + } + } + else { + @T("No media items.") + } +

+ diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Fields/MediaLibraryPicker.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Fields/MediaLibraryPicker.cshtml new file mode 100644 index 000000000..d820bf83d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Fields/MediaLibraryPicker.cshtml @@ -0,0 +1,18 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Fields +@using Orchard.Utility.Extensions; + +@{ + var field = (MediaLibraryPickerField) Model.ContentField; + string name = field.DisplayName; + var contentItems = field.ContentItems; +} +
+

@name

+ @foreach(var contentItem in contentItems) { +
+ @Display(BuildDisplay(contentItem, "Summary")) +
+ } +
+ diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Create.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Create.cshtml new file mode 100644 index 000000000..3b952a7cb --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Create.cshtml @@ -0,0 +1,25 @@ +@model Orchard.MediaLibrary.ViewModels.MediaManagerFolderCreateViewModel +@{ + Layout.Title = T("Add a Folder").ToString(); +} + + + +@using (Html.BeginFormAntiForgeryPost()) { + @Html.ValidationSummary() +
+ + + @Html.HiddenFor(m => m.ParentFolderId) +
+
+ + @Html.ActionLink(T("Cancel").ToString(), "Index", "Admin", new { area = "Orchard.MediaLibrary" }, new { @class= "button"}) +
+ } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Edit.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Edit.cshtml new file mode 100644 index 000000000..f64d2c87b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Folder/Edit.cshtml @@ -0,0 +1,28 @@ +@model Orchard.MediaLibrary.ViewModels.MediaManagerFolderEditViewModel +@{ + Style.Require("MediaManagerAdmin"); + + Layout.Title = T("Edit a Folder").ToString(); +} + + + +@using (Html.BeginFormAntiForgeryPost()) { + @Html.ValidationSummary() +
+ + @Html.TextBoxFor(m => m.Name, new { @class = "textMedium", autofocus = "autofocus"}) + @Html.HiddenFor(m => m.FolderId) +
+
+ + + @Html.ActionLink(T("Cancel").ToString(), "Index", "Admin", new { area = "Orchard.MediaLibrary" }, new { @class= "button"}) +
+ } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Audio.Thumbnail.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Audio.Thumbnail.cshtml new file mode 100644 index 000000000..f34e67d23 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Audio.Thumbnail.cshtml @@ -0,0 +1,12 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@model dynamic + +@{ + ContentItem contentItem = Model.ContentItem; + var media = contentItem.As(); + var audio = contentItem.As(); +} + +@* Don't render the audio tag as thumbnails or the whole file is downloaded automatically by browsers *@ +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Document.Thumbnail.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Document.Thumbnail.cshtml new file mode 100644 index 000000000..fc2b53b99 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Document.Thumbnail.cshtml @@ -0,0 +1,11 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@model dynamic + +@{ + ContentItem contentItem = Model.ContentItem; + var media = contentItem.As(); + var document = contentItem.As(); +} + +
diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Image.Thumbnail.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Image.Thumbnail.cshtml new file mode 100644 index 000000000..f46082dcc --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Image.Thumbnail.cshtml @@ -0,0 +1,11 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@model dynamic + +@{ + ContentItem contentItem = Model.ContentItem; + var media = contentItem.As(); + var image = contentItem.As(); +} + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Video.Thumbnail.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Video.Thumbnail.cshtml new file mode 100644 index 000000000..e204e9025 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media-Video.Thumbnail.cshtml @@ -0,0 +1,12 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@model dynamic + +@{ + ContentItem contentItem = Model.ContentItem; + var media = contentItem.As(); + var video = contentItem.As(); +} + +@* Don't render the video tag as thumbnails or the whole file is downloaded automatically by browsers *@ +
diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.Edit.cshtml new file mode 100644 index 000000000..ee08a573d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.Edit.cshtml @@ -0,0 +1,8 @@ +
+
+ @Display(Model.Content) +
+
+ @Display(Model.Sidebar) +
+
diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.SummaryAdmin.cshtml new file mode 100644 index 000000000..3f13ed96e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.SummaryAdmin.cshtml @@ -0,0 +1,23 @@ +@using Orchard.MediaLibrary.Models +@using Orchard.Utility.Extensions; +@{ + MediaPart mediaPart = Model.ContentItem.MediaPart; + Layout.Title = mediaPart.Title; + var contentTypeClassName = mediaPart.ContentItem.ContentType.HtmlClassify(); +} +
+
+ @Display(Model.Header) + @if (Model.Meta != null) { +
+ @Display(Model.Meta) +
+ } +
+ @Display(Model.Content) + @if(Model.Footer != null) { +
+ @Display(Model.Footer) +
+ } +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.Thumbnail.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.Thumbnail.cshtml new file mode 100644 index 000000000..b9a4228aa --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.Thumbnail.cshtml @@ -0,0 +1,10 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@model dynamic + +@{ + ContentItem contentItem = Model.ContentItem; + var media = contentItem.As(); +} + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.cshtml new file mode 100644 index 000000000..a076f2b8f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.cshtml @@ -0,0 +1,23 @@ +@using Orchard.MediaLibrary.Models +@using Orchard.Utility.Extensions; +@{ + MediaPart mediaPart = Model.ContentItem.MediaPart; + Layout.Title = mediaPart.Title; + var contentTypeClassName = mediaPart.ContentItem.ContentType.HtmlClassify(); +} +
+
+ @Display(Model.Header) + @if (Model.Meta != null) { + + } +
+ @Display(Model.Content) + @if(Model.Footer != null) { +
+ @Display(Model.Footer) +
+ } +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.Metadata.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.Metadata.cshtml new file mode 100644 index 000000000..69cbe120f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.Metadata.cshtml @@ -0,0 +1,9 @@ +@using Orchard.MediaLibrary.Models +@{ + AudioPart audioPart = Model.ContentPart; +} + +
+ @T("Length:") + @T("{0}:{1}", Math.Floor((float)audioPart.Length / 60), Math.Floor((float)audioPart.Length % 60).ToString("00") ) +
diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.Summary.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.Summary.cshtml new file mode 100644 index 000000000..0ae3972e6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.Summary.cshtml @@ -0,0 +1,8 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + AudioPart audioPart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.SummaryAdmin.cshtml new file mode 100644 index 000000000..0ae3972e6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.SummaryAdmin.cshtml @@ -0,0 +1,8 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + AudioPart audioPart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.cshtml new file mode 100644 index 000000000..0ae3972e6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Audio.cshtml @@ -0,0 +1,8 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + AudioPart audioPart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.Metadata.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.Metadata.cshtml new file mode 100644 index 000000000..d3bcfb544 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.Metadata.cshtml @@ -0,0 +1,10 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + DocumentPart documentPart = Model.ContentPart; +} + +
+ @T("Size:") + @T("{0} (KB)", documentPart.Length / 1024) +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.Summary.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.Summary.cshtml new file mode 100644 index 000000000..1420be1ff --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.Summary.cshtml @@ -0,0 +1,11 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + DocumentPart documentPart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + + + + @T("Download") + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.SummaryAdmin.cshtml new file mode 100644 index 000000000..1420be1ff --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.SummaryAdmin.cshtml @@ -0,0 +1,11 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + DocumentPart documentPart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + + + + @T("Download") + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.cshtml new file mode 100644 index 000000000..1420be1ff --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Document.cshtml @@ -0,0 +1,11 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + DocumentPart documentPart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + + + + @T("Download") + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.Metadata.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.Metadata.cshtml new file mode 100644 index 000000000..a9b0359ec --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.Metadata.cshtml @@ -0,0 +1,10 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + ImagePart imagePart = Model.ContentPart; +} + +
+ @T("Dimensions:") + @imagePart.Width x @imagePart.Height +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.Summary.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.Summary.cshtml new file mode 100644 index 000000000..978651fd5 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.Summary.cshtml @@ -0,0 +1,12 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + ImagePart imagePart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + +@* Use a 200x200 profile in order to reuse the general thumbnail *@ + + @mediaPart.AlternateText + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.SummaryAdmin.cshtml new file mode 100644 index 000000000..daa6df582 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.SummaryAdmin.cshtml @@ -0,0 +1,10 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + ImagePart imagePart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + +@* Use a 200x200 profile in order to reuse the general thumbnail *@ +@mediaPart.AlternateText + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.cshtml new file mode 100644 index 000000000..f8322800b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Image.cshtml @@ -0,0 +1,9 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + ImagePart imagePart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + +@mediaPart.AlternateText + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Media.Actions.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Media.Actions.cshtml new file mode 100644 index 000000000..1834f88e8 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Media.Actions.cshtml @@ -0,0 +1,11 @@ +@using Orchard.ContentManagement +@using Orchard.Core.Contents; +@using Orchard.Utility.Extensions +@{ + ContentItem contentItem = Model.ContentItem; + var returnUrl = ViewContext.RequestContext.HttpContext.Request.ToUrlString(); +} + @if (Authorizer.Authorize(Permissions.EditContent, contentItem)) { + @Html.Link(T("Edit").Text, Url.ItemEditUrl(contentItem, new {returnUrl}), new {@class = "button"}) + } + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Media.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Media.SummaryAdmin.cshtml new file mode 100644 index 000000000..2d55983ca --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Media.SummaryAdmin.cshtml @@ -0,0 +1,31 @@ +@using Orchard.MediaLibrary.Models +@{ + MediaPart mediaPart = Model.ContentPart; +} + +
+ @T("Title:") + @mediaPart.Title +
+
+ @T("Filename:") + @Path.GetFileName(mediaPart.Resource) +
+
+ @T("Mime Type:") + @mediaPart.MimeType +
+@if (HasText(mediaPart.Caption)) { +
+ @T("Caption:") + @mediaPart.Caption +
+} + +@if (HasText(mediaPart.AlternateText)) { +
+ @T("Alternate Text:") + @mediaPart.AlternateText +
+} + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.Metadata.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.Metadata.cshtml new file mode 100644 index 000000000..9cafa08d1 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.Metadata.cshtml @@ -0,0 +1,10 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + VideoPart videoPart = Model.ContentPart; +} + +
+ @T("Length:") + @T("{0}:{1}", Math.Floor((float)videoPart.Length / 60), Math.Floor((float)videoPart.Length % 60).ToString("00") ) +
diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.Summary.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.Summary.cshtml new file mode 100644 index 000000000..b65a5f5c6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.Summary.cshtml @@ -0,0 +1,8 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + VideoPart videoPart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.SummaryAdmin.cshtml new file mode 100644 index 000000000..b65a5f5c6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.SummaryAdmin.cshtml @@ -0,0 +1,8 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + VideoPart videoPart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.cshtml new file mode 100644 index 000000000..b65a5f5c6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Video.cshtml @@ -0,0 +1,8 @@ +@using Orchard.ContentManagement +@using Orchard.MediaLibrary.Models +@{ + VideoPart videoPart = Model.ContentPart; + var mediaPart = ((ContentItem)Model.ContentItem).As(); +} + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Web.config b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Web.config new file mode 100644 index 000000000..b7d215131 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Web.config @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/WebSearch/Index.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/WebSearch/Index.cshtml new file mode 100644 index 000000000..8c9f37001 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/WebSearch/Index.cshtml @@ -0,0 +1,227 @@ +@using System.Text + + + + + @{ + Script.Require("jQuery"); + Script.Include("knockout-2.2.1.js"); + + Style.Include("orchard-mediaproviders-admin.css"); + Style.Include("orchard-websearch-admin.css"); + } + + @Display.Metas() + @Display.HeadScripts() + @Display.HeadLinks() + @Display.StyleSheetLinks() + + + +
+ + + + + + +
    +
  • +
    +

    +

    +
    +
  • +
+
+ +
+ + +
+

@T("SELECTION")

+ +
    +
  • +
    +
    +
    +
    +
    +
  • +
+
+
+ + @Html.Hidden("antiforgerytoken", Html.AntiForgeryTokenValueOrchard()) + @Html.Hidden("action", Url.Action("ImagePost")) + @Html.Hidden("id", (int)Model) + + @using(Script.Foot()) { + + } + +@Display.FootScripts() + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Web.config b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Web.config new file mode 100644 index 000000000..88b84a792 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Web.config @@ -0,0 +1,41 @@ + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Media/StorageProviderExtensions.cs b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Media/StorageProviderExtensions.cs index 11bb8a3ca..1f06e313c 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Media/StorageProviderExtensions.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Media/StorageProviderExtensions.cs @@ -2,27 +2,20 @@ namespace Orchard.MediaProcessing.Media { public static class StorageProviderExtensions { - public static bool FileExists(this IStorageProvider storageProvider, string path) { - try { - storageProvider.GetFile(path); - return true; - } - catch {} - return false; - } - public static void TryDeleteFolder(this IStorageProvider storageProvider, string path) { try { - storageProvider.DeleteFolder(path); + if (storageProvider.FolderExists(path)) { + storageProvider.DeleteFolder(path); + } } catch {} } public static IStorageFile OpenOrCreate(this IStorageProvider storageProvider, string path) { - try { + if (!storageProvider.FileExists(path)) { return storageProvider.CreateFile(path); } - catch {} + return storageProvider.GetFile(path); } } diff --git a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProcessingFileNameProvider.cs b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProcessingFileNameProvider.cs index 39c32c7a9..fd760d9fe 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProcessingFileNameProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Services/ImageProcessingFileNameProvider.cs @@ -21,12 +21,13 @@ namespace Orchard.MediaProcessing.Services { if (!fileNames.TryGetValue(path, out fileName)) { var profilePart = _imageProfileService.GetImageProfileByName(profile); if (profilePart != null) { - var fileNameRecord = profilePart.FileNames.FirstOrDefault(f => f.Path == path); - if (fileNameRecord == null) { - return null; + + foreach (var fileNameRecord in profilePart.FileNames) { + fileNames.Add(path, fileNameRecord.FileName); } - fileNames.Add(path, fileNameRecord.FileName); - return fileNameRecord.FileName; + + // now the cache has been initialized, call the same method again + return GetFileName(profile, path); } } return fileName; @@ -40,15 +41,19 @@ namespace Orchard.MediaProcessing.Services { } fileNames[path] = fileName; var profilePart = _imageProfileService.GetImageProfileByName(profile); - var fileNameRecord = profilePart.FileNames.FirstOrDefault(f => f.Path == path); - if (fileNameRecord == null) { - fileNameRecord = new FileNameRecord { - Path = path, - ImageProfilePartRecord = profilePart.Record - }; - profilePart.FileNames.Add(fileNameRecord); + + // profile might not exist in the db if its a dynamic profile + if (profilePart != null) { + var fileNameRecord = profilePart.FileNames.FirstOrDefault(f => f.Path == path); + if (fileNameRecord == null) { + fileNameRecord = new FileNameRecord { + Path = path, + ImageProfilePartRecord = profilePart.Record + }; + profilePart.FileNames.Add(fileNameRecord); + } + fileNameRecord.FileName = fileName; } - fileNameRecord.FileName = fileName; } private Dictionary GetFileNames(string profile) { diff --git a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Shapes/MediaShapes.cs b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Shapes/MediaShapes.cs index d582aa2dc..c4a6cf2f7 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Shapes/MediaShapes.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Shapes/MediaShapes.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net; @@ -12,6 +13,7 @@ using Orchard.Forms.Services; using Orchard.Logging; using Orchard.MediaProcessing.Descriptors.Filter; using Orchard.MediaProcessing.Media; +using Orchard.MediaProcessing.Models; using Orchard.MediaProcessing.Services; using Orchard.Tokens; using Orchard.Utility.Extensions; @@ -44,68 +46,139 @@ namespace Orchard.MediaProcessing.Shapes { public ILogger Logger { get; set; } [Shape] - public void MediaUrl(dynamic Display, TextWriter Output, string Profile, string Path, ContentItem ContentItem) { + public void ResizeMediaUrl(dynamic Display, TextWriter Output, ContentItem ContentItem, string Path, int Width, int Height, string Mode, string Alignment, string PadColor) { + var state = new Dictionary { + {"Width", Width.ToString(CultureInfo.InvariantCulture)}, + {"Height", Height.ToString(CultureInfo.InvariantCulture)}, + {"Mode", Mode}, + {"Alignment", Alignment}, + {"PadColor", PadColor}, + }; + + var filter = new FilterRecord { + Category = "Transform", + Type = "Resize", + State = FormParametersHelper.ToString(state) + }; + + var profile = "Transform_Resize" + + "_w_" + Convert.ToString(Width) + + "_h_" + Convert.ToString(Height) + + "_m_" + Convert.ToString(Mode) + + "_a_" + Convert.ToString(Alignment) + + "_c_" + Convert.ToString(PadColor); + + MediaUrl(Display, Output, profile, Path, ContentItem, filter); + } + + [Shape] + public void MediaUrl(dynamic Display, TextWriter Output, string Profile, string Path, ContentItem ContentItem, FilterRecord CustomFilter) { + + var services = new Lazy(() => _services.Value); + var storageProvider = new Lazy(() => _storageProvider.Value); + + // try to load the processed filename from cache var filePath = _fileNameProvider.Value.GetFileName(Profile, Path); - // todo: regenerate the file if the profile is newer, by getting IStorageFile. - if (string.IsNullOrEmpty(filePath) || !_storageProvider.Value.FileExists(filePath)) { + bool process = false; + + // if the filename is not cached, process it + if (!string.IsNullOrEmpty(filePath)) { + process = true; + } + + // the processd file doesn't exist anymore, process it + else if (!storageProvider.Value.FileExists(filePath)) { + process = true; + } + + // if the original file is more recent, process it + else if (storageProvider.Value.GetFile(Path).GetLastUpdated() > storageProvider.Value.GetFile(filePath).GetLastUpdated()) { + process = true; + } + + // todo: regenerate the file if the profile is newer, by deleting the associated filename cache entries. + if (process) { try { - var profilePart = _profileService.Value.GetImageProfileByName(Profile); - if (profilePart == null) - return; + ImageProfilePart profilePart; - var image = GetImage(Path); - var filterContext = new FilterContext {Media = image, Format = new FileInfo(Path).Extension, FilePath = _storageProvider.Value.Combine(Profile, CreateDefaultFileName(Path))}; - - var tokens = new Dictionary(); - // if a content item is provided, use it while tokenizing - if (ContentItem != null) { - tokens.Add("Content", ContentItem); + if (CustomFilter == null) { + profilePart = _profileService.Value.GetImageProfileByName(Profile); + if (profilePart == null) + return; + } + else { + profilePart = services.Value.ContentManager.New("ImageProfile"); + profilePart.Filters.Add(CustomFilter); } - foreach (var filter in profilePart.Filters.OrderBy(f => f.Position)) { - var descriptor = _processingManager.Value.DescribeFilters().SelectMany(x => x.Descriptors).FirstOrDefault(x => x.Category == filter.Category && x.Type == filter.Type); - if (descriptor == null) - continue; + using (var image = GetImage(Path)) { + var filterContext = new FilterContext {Media = image, Format = new FileInfo(Path).Extension, FilePath = storageProvider.Value.Combine(Profile, CreateDefaultFileName(Path))}; - var tokenized = _tokenizer.Value.Replace(filter.State, tokens); - filterContext.State = FormParametersHelper.ToDynamic(tokenized); - descriptor.Filter(filterContext); - } + var tokens = new Dictionary(); + // if a content item is provided, use it while tokenizing + if (ContentItem != null) { + tokens.Add("Content", ContentItem); + } - _fileNameProvider.Value.UpdateFileName(Profile, Path, filterContext.FilePath); + foreach (var filter in profilePart.Filters.OrderBy(f => f.Position)) { + var descriptor = _processingManager.Value.DescribeFilters().SelectMany(x => x.Descriptors).FirstOrDefault(x => x.Category == filter.Category && x.Type == filter.Type); + if (descriptor == null) + continue; - if (!filterContext.Saved) { - _storageProvider.Value.TryCreateFolder(profilePart.Name); - var newFile = _storageProvider.Value.OpenOrCreate(filterContext.FilePath); - using (var imageStream = newFile.OpenWrite()) { - using (var sw = new BinaryWriter(imageStream)) { - if (filterContext.Media.CanSeek) { - filterContext.Media.Seek(0, SeekOrigin.Begin); - } - using (var sr = new BinaryReader(filterContext.Media)) { - int count; - var buffer = new byte[8192]; - while ((count = sr.Read(buffer, 0, buffer.Length)) != 0) { - sw.Write(buffer, 0, count); + var tokenized = _tokenizer.Value.Replace(filter.State, tokens); + filterContext.State = FormParametersHelper.ToDynamic(tokenized); + descriptor.Filter(filterContext); + } + + _fileNameProvider.Value.UpdateFileName(Profile, Path, filterContext.FilePath); + + if (!filterContext.Saved) { + storageProvider.Value.TryCreateFolder(profilePart.Name); + var newFile = storageProvider.Value.OpenOrCreate(filterContext.FilePath); + using (var imageStream = newFile.OpenWrite()) { + using (var sw = new BinaryWriter(imageStream)) { + if (filterContext.Media.CanSeek) { + filterContext.Media.Seek(0, SeekOrigin.Begin); + } + using (var sr = new BinaryReader(filterContext.Media)) { + int count; + var buffer = new byte[8192]; + while ((count = sr.Read(buffer, 0, buffer.Length)) != 0) { + sw.Write(buffer, 0, count); + } } } } } - } - filterContext.Media.Dispose(); - filePath = filterContext.FilePath; + filterContext.Media.Dispose(); + filePath = filterContext.FilePath; + } } catch (Exception ex) { Logger.Error(ex, "An error occured while processing {0} for image {1}", Profile, Path); return; } } - Output.Write(_storageProvider.Value.GetPublicUrl(filePath)); + + // generate a timestamped url to force client caches to update if the file has changed + var publicUrl = storageProvider.Value.GetPublicUrl(filePath); + var timestamp = storageProvider.Value.GetFile(storageProvider.Value.GetLocalPath(filePath)).GetLastUpdated().Ticks; + Output.Write(publicUrl + "?v=" + timestamp.ToString(CultureInfo.InvariantCulture)); } // TODO: Update this method once the storage provider has been updated private Stream GetImage(string path) { + var storageProvider = new Lazy(() => _storageProvider.Value); + var services = new Lazy(() => _services.Value); + + var request = services.Value.WorkContext.HttpContext.Request; + + // /OrchardLocal/images/my-image.jpg + if (Uri.IsWellFormedUriString(path, UriKind.Relative)) { + path = storageProvider.Value.GetLocalPath(path); + } + // http://blob.storage-provider.net/my-image.jpg if (Uri.IsWellFormedUriString(path, UriKind.Absolute)) { var webClient = new WebClient(); @@ -114,10 +187,11 @@ namespace Orchard.MediaProcessing.Shapes { // ~/Media/Default/images/my-image.jpg if (VirtualPathUtility.IsAppRelative(path)) { var webClient = new WebClient(); - return webClient.OpenRead(new Uri(_services.Value.WorkContext.HttpContext.Request.Url, VirtualPathUtility.ToAbsolute(path))); + return webClient.OpenRead(new Uri(request.Url, VirtualPathUtility.ToAbsolute(path))); } + // images/my-image.jpg - var file = _storageProvider.Value.GetFile(path); + var file = storageProvider.Value.GetFile(path); return file.OpenRead(); } diff --git a/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj b/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj index 8b636a87a..a7de95fd7 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj +++ b/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj @@ -21,6 +21,10 @@ false + + + + true @@ -113,9 +117,7 @@ - - Designer - + diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Orchard.jQuery.csproj b/src/Orchard.Web/Modules/Orchard.jQuery/Orchard.jQuery.csproj index 56b693c1a..3b393c4e7 100644 --- a/src/Orchard.Web/Modules/Orchard.jQuery/Orchard.jQuery.csproj +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Orchard.jQuery.csproj @@ -53,6 +53,11 @@ + + + + + @@ -61,6 +66,16 @@ + + + + + jquery.fileupload.js + + + + jquery.iframe-transport.js + diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/ResourceManifest.cs b/src/Orchard.Web/Modules/Orchard.jQuery/ResourceManifest.cs index 59893c7e1..b7ba9d41c 100644 --- a/src/Orchard.Web/Modules/Orchard.jQuery/ResourceManifest.cs +++ b/src/Orchard.Web/Modules/Orchard.jQuery/ResourceManifest.cs @@ -65,6 +65,14 @@ namespace Orchard.jQuery { manifest.DefineStyle("jQueryUI_Orchard").SetUrl("jquery-ui-1.9.2.custom.css").SetVersion("1.9.2"); manifest.DefineStyle("jQueryUI_DatePicker").SetUrl("ui.datepicker.css").SetDependencies("jQueryUI_Orchard").SetVersion("1.7.2"); manifest.DefineStyle("jQueryUI_TimePicker").SetUrl("jquery-ui-timepicker-addon.css").SetDependencies("jQueryUI_Orchard").SetVersion("1.0.5"); + + // jQuery File Upload + manifest.DefineScript("jQueryIFrameTransport").SetUrl("jquery.iframe-transport.min.js", "jquery.iframe-transport.js").SetVersion("1.6.1").SetDependencies("jQuery"); + manifest.DefineScript("jQueryFileUpload").SetUrl("jquery.fileupload.min.js", "jquery.fileupload.js").SetVersion("1.6.1").SetDependencies("jQueryIFrameTransport").SetDependencies("jQueryUI_Widget"); + + // jquer Color Box + manifest.DefineScript("jQueryColorBox").SetUrl("jquery.colorbox.min.js", "jquery.colorbox.js").SetVersion("1.4.10").SetDependencies("jQuery"); + manifest.DefineStyle("jQueryColorBox").SetUrl("colorbox.css").SetVersion("1.4.10"); } } } diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.colorbox-min.js b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.colorbox-min.js new file mode 100644 index 000000000..712355d17 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.colorbox-min.js @@ -0,0 +1,6 @@ +/*! + jQuery Colorbox v1.4.10 - 2013-04-02 + (c) 2013 Jack Moore - jacklmoore.com/colorbox + license: http://www.opensource.org/licenses/mit-license.php +*/ +(function(e,t,i){function o(i,o,n){var r=t.createElement(i);return o&&(r.id=et+o),n&&(r.style.cssText=n),e(r)}function n(){return i.innerHeight?i.innerHeight:e(i).height()}function r(e){var t=H.length,i=(j+e)%t;return 0>i?t+i:i}function h(e,t){return Math.round((/%/.test(e)?("x"===t?E.width():n())/100:1)*parseInt(e,10))}function s(e,t){return e.photo||e.photoRegex.test(t)}function l(e,t){return e.retinaUrl&&i.devicePixelRatio>1?t.replace(e.photoRegex,e.retinaSuffix):t}function a(e){"contains"in v[0]&&!v[0].contains(e.target)&&(e.stopPropagation(),v.focus())}function d(){var t,i=e.data(O,Z);null==i?(D=e.extend({},Y),console&&console.log&&console.log("Error: cboxElement missing settings object")):D=e.extend({},i);for(t in D)e.isFunction(D[t])&&"on"!==t.slice(0,2)&&(D[t]=D[t].call(O));D.rel=D.rel||O.rel||e(O).data("rel")||"nofollow",D.href=D.href||e(O).attr("href"),D.title=D.title||O.title,"string"==typeof D.href&&(D.href=e.trim(D.href))}function c(i,o){e(t).trigger(i),lt.trigger(i),e.isFunction(o)&&o.call(O)}function u(){var e,t,i,o,n,r=et+"Slideshow_",h="click."+et;D.slideshow&&H[1]?(t=function(){clearTimeout(e)},i=function(){(D.loop||H[j+1])&&(e=setTimeout(J.next,D.slideshowSpeed))},o=function(){M.html(D.slideshowStop).unbind(h).one(h,n),lt.bind(nt,i).bind(ot,t).bind(rt,n),v.removeClass(r+"off").addClass(r+"on")},n=function(){t(),lt.unbind(nt,i).unbind(ot,t).unbind(rt,n),M.html(D.slideshowStart).unbind(h).one(h,function(){J.next(),o()}),v.removeClass(r+"on").addClass(r+"off")},D.slideshowAuto?o():n()):v.removeClass(r+"off "+r+"on")}function f(i){G||(O=i,d(),H=e(O),j=0,"nofollow"!==D.rel&&(H=e("."+tt).filter(function(){var t,i=e.data(this,Z);return i&&(t=e(this).data("rel")||i.rel||this.rel),t===D.rel}),j=H.index(O),-1===j&&(H=H.add(O),j=H.length-1)),g.css({opacity:parseFloat(D.opacity),cursor:D.overlayClose?"pointer":"auto",visibility:"visible"}).show(),V&&v.add(g).removeClass(V),D.className&&v.add(g).addClass(D.className),V=D.className,K.html(D.close).show(),$||($=q=!0,v.css({visibility:"hidden",display:"block"}),W=o(at,"LoadedContent","width:0; height:0; overflow:hidden").appendTo(y),B=b.height()+k.height()+y.outerHeight(!0)-y.height(),N=C.width()+T.width()+y.outerWidth(!0)-y.width(),z=W.outerHeight(!0),A=W.outerWidth(!0),D.w=h(D.initialWidth,"x"),D.h=h(D.initialHeight,"y"),J.position(),u(),c(it,D.onOpen),_.add(F).hide(),v.focus(),t.addEventListener&&(t.addEventListener("focus",a,!0),lt.one(ht,function(){t.removeEventListener("focus",a,!0)})),D.returnFocus&<.one(ht,function(){e(O).focus()})),w())}function p(){!v&&t.body&&(X=!1,E=e(i),v=o(at).attr({id:Z,"class":e.support.opacity===!1?et+"IE":"",role:"dialog",tabindex:"-1"}).hide(),g=o(at,"Overlay").hide(),S=o(at,"LoadingOverlay").add(o(at,"LoadingGraphic")),x=o(at,"Wrapper"),y=o(at,"Content").append(F=o(at,"Title"),I=o(at,"Current"),P=o("button","Previous"),R=o("button","Next"),M=o("button","Slideshow"),S,K=o("button","Close")),x.append(o(at).append(o(at,"TopLeft"),b=o(at,"TopCenter"),o(at,"TopRight")),o(at,!1,"clear:left").append(C=o(at,"MiddleLeft"),y,T=o(at,"MiddleRight")),o(at,!1,"clear:left").append(o(at,"BottomLeft"),k=o(at,"BottomCenter"),o(at,"BottomRight"))).find("div div").css({"float":"left"}),L=o(at,!1,"position:absolute; width:9999px; visibility:hidden; display:none"),_=R.add(P).add(I).add(M),e(t.body).append(g,v.append(x,L)))}function m(){function i(e){e.which>1||e.shiftKey||e.altKey||e.metaKey||e.control||(e.preventDefault(),f(this))}return v?(X||(X=!0,R.click(function(){J.next()}),P.click(function(){J.prev()}),K.click(function(){J.close()}),g.click(function(){D.overlayClose&&J.close()}),e(t).bind("keydown."+et,function(e){var t=e.keyCode;$&&D.escKey&&27===t&&(e.preventDefault(),J.close()),$&&D.arrowKey&&H[1]&&!e.altKey&&(37===t?(e.preventDefault(),P.click()):39===t&&(e.preventDefault(),R.click()))}),e.isFunction(e.fn.on)?e(t).on("click."+et,"."+tt,i):e("."+tt).live("click."+et,i)),!0):!1}function w(){var t,n,r,a=J.prep,u=++dt;q=!0,U=!1,O=H[j],d(),c(st),c(ot,D.onLoad),D.h=D.height?h(D.height,"y")-z-B:D.innerHeight&&h(D.innerHeight,"y"),D.w=D.width?h(D.width,"x")-A-N:D.innerWidth&&h(D.innerWidth,"x"),D.mw=D.w,D.mh=D.h,D.maxWidth&&(D.mw=h(D.maxWidth,"x")-A-N,D.mw=D.w&&D.w1&&(U.height=U.height/i.devicePixelRatio,U.width=U.width/i.devicePixelRatio),D.scalePhotos&&(n=function(){U.height-=U.height*e,U.width-=U.width*e},D.mw&&U.width>D.mw&&(e=(U.width-D.mw)/U.width,n()),D.mh&&U.height>D.mh&&(e=(U.height-D.mh)/U.height,n())),D.h&&(U.style.marginTop=Math.max(D.mh-U.height,0)/2+"px"),H[1]&&(D.loop||H[j+1])&&(U.style.cursor="pointer",U.onclick=function(){J.next()}),setTimeout(function(){a(U)},1))}),setTimeout(function(){U.src=t},1)):t&&L.load(t,D.data,function(t,i){u===dt&&a("error"===i?o(at,"Error").html(D.xhrError):e(this).contents())})}var g,v,x,y,b,C,T,k,H,E,W,L,S,F,I,M,R,P,K,_,D,B,N,z,A,O,j,U,$,q,G,Q,J,V,X,Y={transition:"elastic",speed:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,inline:!1,html:!1,iframe:!1,fastIframe:!0,photo:!1,href:!1,title:!1,rel:!1,opacity:.9,preloading:!0,className:!1,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",open:!1,returnFocus:!0,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico)((#|\?).*)?$/i,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:void 0},Z="colorbox",et="cbox",tt=et+"Element",it=et+"_open",ot=et+"_load",nt=et+"_complete",rt=et+"_cleanup",ht=et+"_closed",st=et+"_purge",lt=e(""),at="div",dt=0;e.colorbox||(e(p),J=e.fn[Z]=e[Z]=function(t,i){var o=this;if(t=t||{},p(),m()){if(e.isFunction(o))o=e(""),t.open=!0;else if(!o[0])return o;i&&(t.onComplete=i),o.each(function(){e.data(this,Z,e.extend({},e.data(this,Z)||Y,t))}).addClass(tt),(e.isFunction(t.open)&&t.open.call(o)||t.open)&&f(o[0])}return o},J.position=function(e,t){function i(e){b[0].style.width=k[0].style.width=y[0].style.width=parseInt(e.style.width,10)-N+"px",y[0].style.height=C[0].style.height=T[0].style.height=parseInt(e.style.height,10)-B+"px"}var o,r,s,l=0,a=0,d=v.offset();E.unbind("resize."+et),v.css({top:-9e4,left:-9e4}),r=E.scrollTop(),s=E.scrollLeft(),D.fixed?(d.top-=r,d.left-=s,v.css({position:"fixed"})):(l=r,a=s,v.css({position:"absolute"})),a+=D.right!==!1?Math.max(E.width()-D.w-A-N-h(D.right,"x"),0):D.left!==!1?h(D.left,"x"):Math.round(Math.max(E.width()-D.w-A-N,0)/2),l+=D.bottom!==!1?Math.max(n()-D.h-z-B-h(D.bottom,"y"),0):D.top!==!1?h(D.top,"y"):Math.round(Math.max(n()-D.h-z-B,0)/2),v.css({top:d.top,left:d.left,visibility:"visible"}),e=v.width()===D.w+A&&v.height()===D.h+z?0:e||0,x[0].style.width=x[0].style.height="9999px",o={width:D.w+A+N,height:D.h+z+B,top:l,left:a},0===e&&v.css(o),v.dequeue().animate(o,{duration:e,complete:function(){i(this),q=!1,x[0].style.width=D.w+A+N+"px",x[0].style.height=D.h+z+B+"px",D.reposition&&setTimeout(function(){E.bind("resize."+et,J.position)},1),t&&t()},step:function(){i(this)}})},J.resize=function(e){$&&(e=e||{},e.width&&(D.w=h(e.width,"x")-A-N),e.innerWidth&&(D.w=h(e.innerWidth,"x")),W.css({width:D.w}),e.height&&(D.h=h(e.height,"y")-z-B),e.innerHeight&&(D.h=h(e.innerHeight,"y")),e.innerHeight||e.height||(W.css({height:"auto"}),D.h=W.height()),W.css({height:D.h}),J.position("none"===D.transition?0:D.speed))},J.prep=function(t){function i(){return D.w=D.w||W.width(),D.w=D.mw&&D.mw1?("string"==typeof D.current&&I.html(D.current.replace("{current}",j+1).replace("{total}",h)).show(),R[D.loop||h-1>j?"show":"hide"]().html(D.next),P[D.loop||j?"show":"hide"]().html(D.previous),D.slideshow&&M.show(),D.preloading&&e.each([r(-1),r(1)],function(){var t,i,o=H[this],n=e.data(o,Z);n&&n.href?(t=n.href,e.isFunction(t)&&(t=t.call(o))):t=e(o).attr("href"),t&&s(n,t)&&(t=l(n,t),i=new Image,i.src=t)})):_.hide(),D.iframe?(i=o("iframe")[0],d in i&&(i[d]=0),u in i&&(i[u]="true"),D.scrolling||(i.scrolling="no"),e(i).attr({src:D.href,name:(new Date).getTime(),"class":et+"Iframe",allowFullScreen:!0,webkitAllowFullScreen:!0,mozallowfullscreen:!0}).one("load",n).appendTo(W),lt.one(st,function(){i.src="//about:blank"}),D.fastIframe&&e(i).trigger("load")):n(),"fade"===D.transition?v.fadeTo(a,1,t):t())},"fade"===D.transition?v.fadeTo(a,0,function(){J.position(0,h)}):J.position(a,h)}},J.next=function(){!q&&H[1]&&(D.loop||H[j+1])&&(j=r(1),f(H[j]))},J.prev=function(){!q&&H[1]&&(D.loop||j)&&(j=r(-1),f(H[j]))},J.close=function(){$&&!G&&(G=!0,$=!1,c(rt,D.onCleanup),E.unbind("."+et),g.fadeTo(200,0),v.stop().fadeTo(300,0,function(){v.add(g).css({opacity:1,cursor:"auto"}).hide(),c(st),W.empty().remove(),setTimeout(function(){G=!1,c(ht,D.onClosed)},1)}))},J.remove=function(){v&&(v.stop(),e.colorbox.close(),v.stop().remove(),g.remove(),G=!1,v=null,e("."+tt).removeData(Z).removeClass(tt),e(t).unbind("click."+et))},J.element=function(){return e(O)},J.settings=Y)})(jQuery,document,window); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.colorbox.js b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.colorbox.js new file mode 100644 index 000000000..72bbc1d01 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.colorbox.js @@ -0,0 +1,1020 @@ +/*! + jQuery Colorbox v1.4.10 - 2013-04-02 + (c) 2013 Jack Moore - jacklmoore.com/colorbox + license: http://www.opensource.org/licenses/mit-license.php +*/ +(function ($, document, window) { + var + // Default settings object. + // See http://jacklmoore.com/colorbox for details. + defaults = { + transition: "elastic", + speed: 300, + width: false, + initialWidth: "600", + innerWidth: false, + maxWidth: false, + height: false, + initialHeight: "450", + innerHeight: false, + maxHeight: false, + scalePhotos: true, + scrolling: true, + inline: false, + html: false, + iframe: false, + fastIframe: true, + photo: false, + href: false, + title: false, + rel: false, + opacity: 0.9, + preloading: true, + className: false, + + // alternate image paths for high-res displays + retinaImage: false, + retinaUrl: false, + retinaSuffix: '@2x.$1', + + // internationalization + current: "image {current} of {total}", + previous: "previous", + next: "next", + close: "close", + xhrError: "This content failed to load.", + imgError: "This image failed to load.", + + open: false, + returnFocus: true, + reposition: true, + loop: true, + slideshow: false, + slideshowAuto: true, + slideshowSpeed: 2500, + slideshowStart: "start slideshow", + slideshowStop: "stop slideshow", + photoRegex: /\.(gif|png|jp(e|g|eg)|bmp|ico)((#|\?).*)?$/i, + + onOpen: false, + onLoad: false, + onComplete: false, + onCleanup: false, + onClosed: false, + overlayClose: true, + escKey: true, + arrowKey: true, + top: false, + bottom: false, + left: false, + right: false, + fixed: false, + data: undefined + }, + + // Abstracting the HTML and event identifiers for easy rebranding + colorbox = 'colorbox', + prefix = 'cbox', + boxElement = prefix + 'Element', + + // Events + event_open = prefix + '_open', + event_load = prefix + '_load', + event_complete = prefix + '_complete', + event_cleanup = prefix + '_cleanup', + event_closed = prefix + '_closed', + event_purge = prefix + '_purge', + + // Cached jQuery Object Variables + $overlay, + $box, + $wrap, + $content, + $topBorder, + $leftBorder, + $rightBorder, + $bottomBorder, + $related, + $window, + $loaded, + $loadingBay, + $loadingOverlay, + $title, + $current, + $slideshow, + $next, + $prev, + $close, + $groupControls, + $events = $(''), + + // Variables for cached values or use across multiple functions + settings, + interfaceHeight, + interfaceWidth, + loadedHeight, + loadedWidth, + element, + index, + photo, + open, + active, + closing, + loadingTimer, + publicMethod, + div = "div", + className, + requests = 0, + init; + + // **************** + // HELPER FUNCTIONS + // **************** + + // Convience function for creating new jQuery objects + function $tag(tag, id, css) { + var element = document.createElement(tag); + + if (id) { + element.id = prefix + id; + } + + if (css) { + element.style.cssText = css; + } + + return $(element); + } + + // Get the window height using innerHeight when available to avoid an issue with iOS + // http://bugs.jquery.com/ticket/6724 + function winheight() { + return window.innerHeight ? window.innerHeight : $(window).height(); + } + + // Determine the next and previous members in a group. + function getIndex(increment) { + var + max = $related.length, + newIndex = (index + increment) % max; + + return (newIndex < 0) ? max + newIndex : newIndex; + } + + // Convert '%' and 'px' values to integers + function setSize(size, dimension) { + return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10)); + } + + // Checks an href to see if it is a photo. + // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex. + function isImage(settings, url) { + return settings.photo || settings.photoRegex.test(url); + } + + function retinaUrl(settings, url) { + return settings.retinaUrl && window.devicePixelRatio > 1 ? url.replace(settings.photoRegex, settings.retinaSuffix) : url; + } + + function trapFocus(e) { + if ('contains' in $box[0] && !$box[0].contains(e.target)) { + e.stopPropagation(); + $box.focus(); + } + } + + // Assigns function results to their respective properties + function makeSettings() { + var i, + data = $.data(element, colorbox); + + if (data == null) { + settings = $.extend({}, defaults); + if (console && console.log) { + console.log('Error: cboxElement missing settings object'); + } + } else { + settings = $.extend({}, data); + } + + for (i in settings) { + if ($.isFunction(settings[i]) && i.slice(0, 2) !== 'on') { // checks to make sure the function isn't one of the callbacks, they will be handled at the appropriate time. + settings[i] = settings[i].call(element); + } + } + + settings.rel = settings.rel || element.rel || $(element).data('rel') || 'nofollow'; + settings.href = settings.href || $(element).attr('href'); + settings.title = settings.title || element.title; + + if (typeof settings.href === "string") { + settings.href = $.trim(settings.href); + } + } + + function trigger(event, callback) { + // for external use + $(document).trigger(event); + + // for internal use + $events.trigger(event); + + if ($.isFunction(callback)) { + callback.call(element); + } + } + + // Slideshow functionality + function slideshow() { + var + timeOut, + className = prefix + "Slideshow_", + click = "click." + prefix, + clear, + set, + start, + stop; + + if (settings.slideshow && $related[1]) { + clear = function () { + clearTimeout(timeOut); + }; + + set = function () { + if (settings.loop || $related[index + 1]) { + timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed); + } + }; + + start = function () { + $slideshow + .html(settings.slideshowStop) + .unbind(click) + .one(click, stop); + + $events + .bind(event_complete, set) + .bind(event_load, clear) + .bind(event_cleanup, stop); + + $box.removeClass(className + "off").addClass(className + "on"); + }; + + stop = function () { + clear(); + + $events + .unbind(event_complete, set) + .unbind(event_load, clear) + .unbind(event_cleanup, stop); + + $slideshow + .html(settings.slideshowStart) + .unbind(click) + .one(click, function () { + publicMethod.next(); + start(); + }); + + $box.removeClass(className + "on").addClass(className + "off"); + }; + + if (settings.slideshowAuto) { + start(); + } else { + stop(); + } + } else { + $box.removeClass(className + "off " + className + "on"); + } + } + + function launch(target) { + if (!closing) { + + element = target; + + makeSettings(); + + $related = $(element); + + index = 0; + + if (settings.rel !== 'nofollow') { + $related = $('.' + boxElement).filter(function () { + var data = $.data(this, colorbox), + relRelated; + + if (data) { + relRelated = $(this).data('rel') || data.rel || this.rel; + } + + return (relRelated === settings.rel); + }); + index = $related.index(element); + + // Check direct calls to Colorbox. + if (index === -1) { + $related = $related.add(element); + index = $related.length - 1; + } + } + + $overlay.css({ + opacity: parseFloat(settings.opacity), + cursor: settings.overlayClose ? "pointer" : "auto", + visibility: 'visible' + }).show(); + + + if (className) { + $box.add($overlay).removeClass(className); + } + if (settings.className) { + $box.add($overlay).addClass(settings.className); + } + className = settings.className; + + $close.html(settings.close).show(); + + if (!open) { + open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys. + + // Show colorbox so the sizes can be calculated in older versions of jQuery + $box.css({visibility:'hidden', display:'block'}); + + $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden').appendTo($content); + + // Cache values needed for size calculations + interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height(); + interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width(); + loadedHeight = $loaded.outerHeight(true); + loadedWidth = $loaded.outerWidth(true); + + + // Opens inital empty Colorbox prior to content being loaded. + settings.w = setSize(settings.initialWidth, 'x'); + settings.h = setSize(settings.initialHeight, 'y'); + publicMethod.position(); + + slideshow(); + + trigger(event_open, settings.onOpen); + + $groupControls.add($title).hide(); + + $box.focus(); + + // Confine focus to the modal + // Uses event capturing that is not supported in IE8- + if (document.addEventListener) { + + document.addEventListener('focus', trapFocus, true); + + $events.one(event_closed, function () { + document.removeEventListener('focus', trapFocus, true); + }); + } + + // Return focus on closing + if (settings.returnFocus) { + $events.one(event_closed, function () { + $(element).focus(); + }); + } + } + + load(); + } + } + + // Colorbox's markup needs to be added to the DOM prior to being called + // so that the browser will go ahead and load the CSS background images. + function appendHTML() { + if (!$box && document.body) { + init = false; + $window = $(window); + $box = $tag(div).attr({ + id: colorbox, + 'class': $.support.opacity === false ? prefix + 'IE' : '', // class for optional IE8 & lower targeted CSS. + role: 'dialog', + tabindex: '-1' + }).hide(); + $overlay = $tag(div, "Overlay").hide(); + $loadingOverlay = $tag(div, "LoadingOverlay").add($tag(div, "LoadingGraphic")); + $wrap = $tag(div, "Wrapper"); + $content = $tag(div, "Content").append( + $title = $tag(div, "Title"), + $current = $tag(div, "Current"), + $prev = $tag('button', "Previous"), + $next = $tag('button', "Next"), + $slideshow = $tag('button', "Slideshow"), + $loadingOverlay, + $close = $tag('button', "Close") + ); + + $wrap.append( // The 3x3 Grid that makes up Colorbox + $tag(div).append( + $tag(div, "TopLeft"), + $topBorder = $tag(div, "TopCenter"), + $tag(div, "TopRight") + ), + $tag(div, false, 'clear:left').append( + $leftBorder = $tag(div, "MiddleLeft"), + $content, + $rightBorder = $tag(div, "MiddleRight") + ), + $tag(div, false, 'clear:left').append( + $tag(div, "BottomLeft"), + $bottomBorder = $tag(div, "BottomCenter"), + $tag(div, "BottomRight") + ) + ).find('div div').css({'float': 'left'}); + + $loadingBay = $tag(div, false, 'position:absolute; width:9999px; visibility:hidden; display:none'); + + $groupControls = $next.add($prev).add($current).add($slideshow); + + $(document.body).append($overlay, $box.append($wrap, $loadingBay)); + } + } + + // Add Colorbox's event bindings + function addBindings() { + function clickHandler(e) { + // ignore non-left-mouse-clicks and clicks modified with ctrl / command, shift, or alt. + // See: http://jacklmoore.com/notes/click-events/ + if (!(e.which > 1 || e.shiftKey || e.altKey || e.metaKey || e.control)) { + e.preventDefault(); + launch(this); + } + } + + if ($box) { + if (!init) { + init = true; + + // Anonymous functions here keep the public method from being cached, thereby allowing them to be redefined on the fly. + $next.click(function () { + publicMethod.next(); + }); + $prev.click(function () { + publicMethod.prev(); + }); + $close.click(function () { + publicMethod.close(); + }); + $overlay.click(function () { + if (settings.overlayClose) { + publicMethod.close(); + } + }); + + // Key Bindings + $(document).bind('keydown.' + prefix, function (e) { + var key = e.keyCode; + if (open && settings.escKey && key === 27) { + e.preventDefault(); + publicMethod.close(); + } + if (open && settings.arrowKey && $related[1] && !e.altKey) { + if (key === 37) { + e.preventDefault(); + $prev.click(); + } else if (key === 39) { + e.preventDefault(); + $next.click(); + } + } + }); + + if ($.isFunction($.fn.on)) { + // For jQuery 1.7+ + $(document).on('click.'+prefix, '.'+boxElement, clickHandler); + } else { + // For jQuery 1.3.x -> 1.6.x + // This code is never reached in jQuery 1.9, so do not contact me about 'live' being removed. + // This is not here for jQuery 1.9, it's here for legacy users. + $('.'+boxElement).live('click.'+prefix, clickHandler); + } + } + return true; + } + return false; + } + + // Don't do anything if Colorbox already exists. + if ($.colorbox) { + return; + } + + // Append the HTML when the DOM loads + $(appendHTML); + + + // **************** + // PUBLIC FUNCTIONS + // Usage format: $.colorbox.close(); + // Usage from within an iframe: parent.jQuery.colorbox.close(); + // **************** + + publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) { + var $this = this; + + options = options || {}; + + appendHTML(); + + if (addBindings()) { + if ($.isFunction($this)) { // assume a call to $.colorbox + $this = $(''); + options.open = true; + } else if (!$this[0]) { // colorbox being applied to empty collection + return $this; + } + + if (callback) { + options.onComplete = callback; + } + + $this.each(function () { + $.data(this, colorbox, $.extend({}, $.data(this, colorbox) || defaults, options)); + }).addClass(boxElement); + + if (($.isFunction(options.open) && options.open.call($this)) || options.open) { + launch($this[0]); + } + } + + return $this; + }; + + publicMethod.position = function (speed, loadedCallback) { + var + css, + top = 0, + left = 0, + offset = $box.offset(), + scrollTop, + scrollLeft; + + $window.unbind('resize.' + prefix); + + // remove the modal so that it doesn't influence the document width/height + $box.css({top: -9e4, left: -9e4}); + + scrollTop = $window.scrollTop(); + scrollLeft = $window.scrollLeft(); + + if (settings.fixed) { + offset.top -= scrollTop; + offset.left -= scrollLeft; + $box.css({position: 'fixed'}); + } else { + top = scrollTop; + left = scrollLeft; + $box.css({position: 'absolute'}); + } + + // keeps the top and left positions within the browser's viewport. + if (settings.right !== false) { + left += Math.max($window.width() - settings.w - loadedWidth - interfaceWidth - setSize(settings.right, 'x'), 0); + } else if (settings.left !== false) { + left += setSize(settings.left, 'x'); + } else { + left += Math.round(Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2); + } + + if (settings.bottom !== false) { + top += Math.max(winheight() - settings.h - loadedHeight - interfaceHeight - setSize(settings.bottom, 'y'), 0); + } else if (settings.top !== false) { + top += setSize(settings.top, 'y'); + } else { + top += Math.round(Math.max(winheight() - settings.h - loadedHeight - interfaceHeight, 0) / 2); + } + + $box.css({top: offset.top, left: offset.left, visibility:'visible'}); + + // setting the speed to 0 to reduce the delay between same-sized content. + speed = ($box.width() === settings.w + loadedWidth && $box.height() === settings.h + loadedHeight) ? 0 : speed || 0; + + // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly, + // but it has to be shrank down around the size of div#colorbox when it's done. If not, + // it can invoke an obscure IE bug when using iframes. + $wrap[0].style.width = $wrap[0].style.height = "9999px"; + + function modalDimensions(that) { + $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = (parseInt(that.style.width,10) - interfaceWidth)+'px'; + $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = (parseInt(that.style.height,10) - interfaceHeight)+'px'; + } + + css = {width: settings.w + loadedWidth + interfaceWidth, height: settings.h + loadedHeight + interfaceHeight, top: top, left: left}; + + if(speed===0){ // temporary workaround to side-step jQuery-UI 1.8 bug (http://bugs.jquery.com/ticket/12273) + $box.css(css); + } + $box.dequeue().animate(css, { + duration: speed, + complete: function () { + modalDimensions(this); + + active = false; + + // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation. + $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px"; + $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px"; + + if (settings.reposition) { + setTimeout(function () { // small delay before binding onresize due to an IE8 bug. + $window.bind('resize.' + prefix, publicMethod.position); + }, 1); + } + + if (loadedCallback) { + loadedCallback(); + } + }, + step: function () { + modalDimensions(this); + } + }); + }; + + publicMethod.resize = function (options) { + if (open) { + options = options || {}; + + if (options.width) { + settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth; + } + if (options.innerWidth) { + settings.w = setSize(options.innerWidth, 'x'); + } + $loaded.css({width: settings.w}); + + if (options.height) { + settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight; + } + if (options.innerHeight) { + settings.h = setSize(options.innerHeight, 'y'); + } + if (!options.innerHeight && !options.height) { + $loaded.css({height: "auto"}); + settings.h = $loaded.height(); + } + $loaded.css({height: settings.h}); + + publicMethod.position(settings.transition === "none" ? 0 : settings.speed); + } + }; + + publicMethod.prep = function (object) { + if (!open) { + return; + } + + var callback, speed = settings.transition === "none" ? 0 : settings.speed; + + $loaded.empty().remove(); // Using empty first may prevent some IE7 issues. + + $loaded = $tag(div, 'LoadedContent').append(object); + + function getWidth() { + settings.w = settings.w || $loaded.width(); + settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w; + return settings.w; + } + function getHeight() { + settings.h = settings.h || $loaded.height(); + settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h; + return settings.h; + } + + $loaded.hide() + .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations. + .css({width: getWidth(), overflow: settings.scrolling ? 'auto' : 'hidden'}) + .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height. + .prependTo($content); + + $loadingBay.hide(); + + // floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width. + + $(photo).css({'float': 'none'}); + + callback = function () { + var total = $related.length, + iframe, + frameBorder = 'frameBorder', + allowTransparency = 'allowTransparency', + complete; + + if (!open) { + return; + } + + function removeFilter() { // Needed for IE7 & IE8 in versions of jQuery prior to 1.7.2 + if ($.support.opacity === false) { + $box[0].style.removeAttribute('filter'); + } + } + + complete = function () { + clearTimeout(loadingTimer); + $loadingOverlay.hide(); + trigger(event_complete, settings.onComplete); + }; + + + $title.html(settings.title).add($loaded).show(); + + if (total > 1) { // handle grouping + if (typeof settings.current === "string") { + $current.html(settings.current.replace('{current}', index + 1).replace('{total}', total)).show(); + } + + $next[(settings.loop || index < total - 1) ? "show" : "hide"]().html(settings.next); + $prev[(settings.loop || index) ? "show" : "hide"]().html(settings.previous); + + if (settings.slideshow) { + $slideshow.show(); + } + + // Preloads images within a rel group + if (settings.preloading) { + $.each([getIndex(-1), getIndex(1)], function(){ + var src, + img, + i = $related[this], + data = $.data(i, colorbox); + + if (data && data.href) { + src = data.href; + if ($.isFunction(src)) { + src = src.call(i); + } + } else { + src = $(i).attr('href'); + } + + if (src && isImage(data, src)) { + src = retinaUrl(data, src); + img = new Image(); + img.src = src; + } + }); + } + } else { + $groupControls.hide(); + } + + if (settings.iframe) { + iframe = $tag('iframe')[0]; + + if (frameBorder in iframe) { + iframe[frameBorder] = 0; + } + + if (allowTransparency in iframe) { + iframe[allowTransparency] = "true"; + } + + if (!settings.scrolling) { + iframe.scrolling = "no"; + } + + $(iframe) + .attr({ + src: settings.href, + name: (new Date()).getTime(), // give the iframe a unique name to prevent caching + 'class': prefix + 'Iframe', + allowFullScreen : true, // allow HTML5 video to go fullscreen + webkitAllowFullScreen : true, + mozallowfullscreen : true + }) + .one('load', complete) + .appendTo($loaded); + + $events.one(event_purge, function () { + iframe.src = "//about:blank"; + }); + + if (settings.fastIframe) { + $(iframe).trigger('load'); + } + } else { + complete(); + } + + if (settings.transition === 'fade') { + $box.fadeTo(speed, 1, removeFilter); + } else { + removeFilter(); + } + }; + + if (settings.transition === 'fade') { + $box.fadeTo(speed, 0, function () { + publicMethod.position(0, callback); + }); + } else { + publicMethod.position(speed, callback); + } + }; + + function load () { + var href, setResize, prep = publicMethod.prep, $inline, request = ++requests; + + active = true; + + photo = false; + + element = $related[index]; + + makeSettings(); + + trigger(event_purge); + + trigger(event_load, settings.onLoad); + + settings.h = settings.height ? + setSize(settings.height, 'y') - loadedHeight - interfaceHeight : + settings.innerHeight && setSize(settings.innerHeight, 'y'); + + settings.w = settings.width ? + setSize(settings.width, 'x') - loadedWidth - interfaceWidth : + settings.innerWidth && setSize(settings.innerWidth, 'x'); + + // Sets the minimum dimensions for use in image scaling + settings.mw = settings.w; + settings.mh = settings.h; + + // Re-evaluate the minimum width and height based on maxWidth and maxHeight values. + // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead. + if (settings.maxWidth) { + settings.mw = setSize(settings.maxWidth, 'x') - loadedWidth - interfaceWidth; + settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw; + } + if (settings.maxHeight) { + settings.mh = setSize(settings.maxHeight, 'y') - loadedHeight - interfaceHeight; + settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh; + } + + href = settings.href; + + loadingTimer = setTimeout(function () { + $loadingOverlay.show(); + }, 100); + + if (settings.inline) { + // Inserts an empty placeholder where inline content is being pulled from. + // An event is bound to put inline content back when Colorbox closes or loads new content. + $inline = $tag(div).hide().insertBefore($(href)[0]); + + $events.one(event_purge, function () { + $inline.replaceWith($loaded.children()); + }); + + prep($(href)); + } else if (settings.iframe) { + // IFrame element won't be added to the DOM until it is ready to be displayed, + // to avoid problems with DOM-ready JS that might be trying to run in that iframe. + prep(" "); + } else if (settings.html) { + prep(settings.html); + } else if (isImage(settings, href)) { + + href = retinaUrl(settings, href); + + $(photo = new Image()) + .addClass(prefix + 'Photo') + .bind('error',function () { + settings.title = false; + prep($tag(div, 'Error').html(settings.imgError)); + }) + .one('load', function () { + var percent; + + if (request !== requests) { + return; + } + + if (settings.retinaImage && window.devicePixelRatio > 1) { + photo.height = photo.height / window.devicePixelRatio; + photo.width = photo.width / window.devicePixelRatio; + } + + if (settings.scalePhotos) { + setResize = function () { + photo.height -= photo.height * percent; + photo.width -= photo.width * percent; + }; + if (settings.mw && photo.width > settings.mw) { + percent = (photo.width - settings.mw) / photo.width; + setResize(); + } + if (settings.mh && photo.height > settings.mh) { + percent = (photo.height - settings.mh) / photo.height; + setResize(); + } + } + + if (settings.h) { + photo.style.marginTop = Math.max(settings.mh - photo.height, 0) / 2 + 'px'; + } + + if ($related[1] && (settings.loop || $related[index + 1])) { + photo.style.cursor = 'pointer'; + photo.onclick = function () { + publicMethod.next(); + }; + } + + setTimeout(function () { // A pause because Chrome will sometimes report a 0 by 0 size otherwise. + prep(photo); + }, 1); + }); + + setTimeout(function () { // A pause because Opera 10.6+ will sometimes not run the onload function otherwise. + photo.src = href; + }, 1); + } else if (href) { + $loadingBay.load(href, settings.data, function (data, status) { + if (request === requests) { + prep(status === 'error' ? $tag(div, 'Error').html(settings.xhrError) : $(this).contents()); + } + }); + } + } + + // Navigates to the next page/image in a set. + publicMethod.next = function () { + if (!active && $related[1] && (settings.loop || $related[index + 1])) { + index = getIndex(1); + launch($related[index]); + } + }; + + publicMethod.prev = function () { + if (!active && $related[1] && (settings.loop || index)) { + index = getIndex(-1); + launch($related[index]); + } + }; + + // Note: to use this within an iframe use the following format: parent.jQuery.colorbox.close(); + publicMethod.close = function () { + if (open && !closing) { + + closing = true; + + open = false; + + trigger(event_cleanup, settings.onCleanup); + + $window.unbind('.' + prefix); + + $overlay.fadeTo(200, 0); + + $box.stop().fadeTo(300, 0, function () { + + $box.add($overlay).css({'opacity': 1, cursor: 'auto'}).hide(); + + trigger(event_purge); + + $loaded.empty().remove(); // Using empty first may prevent some IE7 issues. + + setTimeout(function () { + closing = false; + trigger(event_closed, settings.onClosed); + }, 1); + }); + } + }; + + // Removes changes Colorbox made to the document, but does not remove the plugin. + publicMethod.remove = function () { + if (!$box) { return; } + + $box.stop(); + $.colorbox.close(); + $box.stop().remove(); + $overlay.remove(); + closing = false; + $box = null; + $('.' + boxElement) + .removeData(colorbox) + .removeClass(boxElement); + + $(document).unbind('click.'+prefix); + }; + + // A method for fetching the current element Colorbox is referencing. + // returns a jQuery object. + publicMethod.element = function () { + return $(element); + }; + + publicMethod.settings = defaults; + +}(jQuery, document, window)); diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.fileupload.js b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.fileupload.js new file mode 100644 index 000000000..78bffafec --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.fileupload.js @@ -0,0 +1,1233 @@ +/* + * jQuery File Upload Plugin 5.28.5 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, unparam: true, regexp: true */ +/*global define, window, document, File, Blob, FormData, location */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'jquery.ui.widget' + ], factory); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + + // The FileReader API is not actually used, but works as feature detection, + // as e.g. Safari supports XHR file uploads via the FormData API, + // but not non-multipart XHR file uploads: + $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader); + $.support.xhrFormDataFileUpload = !!window.FormData; + + // The fileupload widget listens for change events on file input fields defined + // via fileInput setting and paste or drop events of the given dropZone. + // In addition to the default jQuery Widget methods, the fileupload widget + // exposes the "add" and "send" methods, to add or directly send files using + // the fileupload API. + // By default, files added via file input selection, paste, drag & drop or + // "add" method are uploaded immediately, but it is possible to override + // the "add" callback option to queue file uploads. + $.widget('blueimp.fileupload', { + + options: { + // The drop target element(s), by the default the complete document. + // Set to null to disable drag & drop support: + dropZone: $(document), + // The paste target element(s), by the default the complete document. + // Set to null to disable paste support: + pasteZone: $(document), + // The file input field(s), that are listened to for change events. + // If undefined, it is set to the file input fields inside + // of the widget element on plugin initialization. + // Set to null to disable the change listener. + fileInput: undefined, + // By default, the file input field is replaced with a clone after + // each input field change event. This is required for iframe transport + // queues and allows change events to be fired for the same file + // selection, but can be disabled by setting the following option to false: + replaceFileInput: true, + // The parameter name for the file form data (the request argument name). + // If undefined or empty, the name property of the file input field is + // used, or "files[]" if the file input name property is also empty, + // can be a string or an array of strings: + paramName: undefined, + // By default, each file of a selection is uploaded using an individual + // request for XHR type uploads. Set to false to upload file + // selections in one request each: + singleFileUploads: true, + // To limit the number of files uploaded with one XHR request, + // set the following option to an integer greater than 0: + limitMultiFileUploads: undefined, + // Set the following option to true to issue all file upload requests + // in a sequential order: + sequentialUploads: false, + // To limit the number of concurrent uploads, + // set the following option to an integer greater than 0: + limitConcurrentUploads: undefined, + // Set the following option to true to force iframe transport uploads: + forceIframeTransport: false, + // Set the following option to the location of a redirect url on the + // origin server, for cross-domain iframe transport uploads: + redirect: undefined, + // The parameter name for the redirect url, sent as part of the form + // data and set to 'redirect' if this option is empty: + redirectParamName: undefined, + // Set the following option to the location of a postMessage window, + // to enable postMessage transport uploads: + postMessage: undefined, + // By default, XHR file uploads are sent as multipart/form-data. + // The iframe transport is always using multipart/form-data. + // Set to false to enable non-multipart XHR uploads: + multipart: true, + // To upload large files in smaller chunks, set the following option + // to a preferred maximum chunk size. If set to 0, null or undefined, + // or the browser does not support the required Blob API, files will + // be uploaded as a whole. + maxChunkSize: undefined, + // When a non-multipart upload or a chunked multipart upload has been + // aborted, this option can be used to resume the upload by setting + // it to the size of the already uploaded bytes. This option is most + // useful when modifying the options object inside of the "add" or + // "send" callbacks, as the options are cloned for each file upload. + uploadedBytes: undefined, + // By default, failed (abort or error) file uploads are removed from the + // global progress calculation. Set the following option to false to + // prevent recalculating the global progress data: + recalculateProgress: true, + // Interval in milliseconds to calculate and trigger progress events: + progressInterval: 100, + // Interval in milliseconds to calculate progress bitrate: + bitrateInterval: 500, + // By default, uploads are started automatically when adding files: + autoUpload: true, + + // Additional form data to be sent along with the file uploads can be set + // using this option, which accepts an array of objects with name and + // value properties, a function returning such an array, a FormData + // object (for XHR file uploads), or a simple object. + // The form of the first fileInput is given as parameter to the function: + formData: function (form) { + return form.serializeArray(); + }, + + // The add callback is invoked as soon as files are added to the fileupload + // widget (via file input selection, drag & drop, paste or add API call). + // If the singleFileUploads option is enabled, this callback will be + // called once for each file in the selection for XHR file uplaods, else + // once for each file selection. + // The upload starts when the submit method is invoked on the data parameter. + // The data object contains a files property holding the added files + // and allows to override plugin options as well as define ajax settings. + // Listeners for this callback can also be bound the following way: + // .bind('fileuploadadd', func); + // data.submit() returns a Promise object and allows to attach additional + // handlers using jQuery's Deferred callbacks: + // data.submit().done(func).fail(func).always(func); + add: function (e, data) { + if (data.autoUpload || (data.autoUpload !== false && + ($(this).data('blueimp-fileupload') || + $(this).data('fileupload')).options.autoUpload)) { + data.submit(); + } + }, + + // Other callbacks: + + // Callback for the submit event of each file upload: + // submit: function (e, data) {}, // .bind('fileuploadsubmit', func); + + // Callback for the start of each file upload request: + // send: function (e, data) {}, // .bind('fileuploadsend', func); + + // Callback for successful uploads: + // done: function (e, data) {}, // .bind('fileuploaddone', func); + + // Callback for failed (abort or error) uploads: + // fail: function (e, data) {}, // .bind('fileuploadfail', func); + + // Callback for completed (success, abort or error) requests: + // always: function (e, data) {}, // .bind('fileuploadalways', func); + + // Callback for upload progress events: + // progress: function (e, data) {}, // .bind('fileuploadprogress', func); + + // Callback for global upload progress events: + // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func); + + // Callback for uploads start, equivalent to the global ajaxStart event: + // start: function (e) {}, // .bind('fileuploadstart', func); + + // Callback for uploads stop, equivalent to the global ajaxStop event: + // stop: function (e) {}, // .bind('fileuploadstop', func); + + // Callback for change events of the fileInput(s): + // change: function (e, data) {}, // .bind('fileuploadchange', func); + + // Callback for paste events to the pasteZone(s): + // paste: function (e, data) {}, // .bind('fileuploadpaste', func); + + // Callback for drop events of the dropZone(s): + // drop: function (e, data) {}, // .bind('fileuploaddrop', func); + + // Callback for dragover events of the dropZone(s): + // dragover: function (e) {}, // .bind('fileuploaddragover', func); + + // Callback for the start of each chunk upload request: + // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func); + + // Callback for successful chunk uploads: + // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func); + + // Callback for failed (abort or error) chunk uploads: + // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func); + + // Callback for completed (success, abort or error) chunk upload requests: + // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func); + + // The plugin options are used as settings object for the ajax calls. + // The following are jQuery ajax settings required for the file uploads: + processData: false, + contentType: false, + cache: false + }, + + // A list of options that require a refresh after assigning a new value: + _refreshOptionsList: [ + 'fileInput', + 'dropZone', + 'pasteZone', + 'multipart', + 'forceIframeTransport' + ], + + _BitrateTimer: function () { + this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime()); + this.loaded = 0; + this.bitrate = 0; + this.getBitrate = function (now, loaded, interval) { + var timeDiff = now - this.timestamp; + if (!this.bitrate || !interval || timeDiff > interval) { + this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; + this.loaded = loaded; + this.timestamp = now; + } + return this.bitrate; + }; + }, + + _isXHRUpload: function (options) { + return !options.forceIframeTransport && + ((!options.multipart && $.support.xhrFileUpload) || + $.support.xhrFormDataFileUpload); + }, + + _getFormData: function (options) { + var formData; + if (typeof options.formData === 'function') { + return options.formData(options.form); + } + if ($.isArray(options.formData)) { + return options.formData; + } + if ($.type(options.formData) === 'object') { + formData = []; + $.each(options.formData, function (name, value) { + formData.push({name: name, value: value}); + }); + return formData; + } + return []; + }, + + _getTotal: function (files) { + var total = 0; + $.each(files, function (index, file) { + total += file.size || 1; + }); + return total; + }, + + _initProgressObject: function (obj) { + var progress = { + loaded: 0, + total: 0, + bitrate: 0 + }; + if (obj._progress) { + $.extend(obj._progress, progress); + } else { + obj._progress = progress; + } + }, + + _initResponseObject: function (obj) { + var prop; + if (obj._response) { + for (prop in obj._response) { + if (obj._response.hasOwnProperty(prop)) { + delete obj._response[prop]; + } + } + } else { + obj._response = {}; + } + }, + + _onProgress: function (e, data) { + if (e.lengthComputable) { + var now = ((Date.now) ? Date.now() : (new Date()).getTime()), + loaded; + if (data._time && data.progressInterval && + (now - data._time < data.progressInterval) && + e.loaded !== e.total) { + return; + } + data._time = now; + loaded = Math.floor( + e.loaded / e.total * (data.chunkSize || data._progress.total) + ) + (data.uploadedBytes || 0); + // Add the difference from the previously loaded state + // to the global loaded counter: + this._progress.loaded += (loaded - data._progress.loaded); + this._progress.bitrate = this._bitrateTimer.getBitrate( + now, + this._progress.loaded, + data.bitrateInterval + ); + data._progress.loaded = data.loaded = loaded; + data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate( + now, + loaded, + data.bitrateInterval + ); + // Trigger a custom progress event with a total data property set + // to the file size(s) of the current upload and a loaded data + // property calculated accordingly: + this._trigger('progress', e, data); + // Trigger a global progress event for all current file uploads, + // including ajax calls queued for sequential file uploads: + this._trigger('progressall', e, this._progress); + } + }, + + _initProgressListener: function (options) { + var that = this, + xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); + // Accesss to the native XHR object is required to add event listeners + // for the upload progress event: + if (xhr.upload) { + $(xhr.upload).bind('progress', function (e) { + var oe = e.originalEvent; + // Make sure the progress event properties get copied over: + e.lengthComputable = oe.lengthComputable; + e.loaded = oe.loaded; + e.total = oe.total; + that._onProgress(e, options); + }); + options.xhr = function () { + return xhr; + }; + } + }, + + _initXHRData: function (options) { + var formData, + file = options.files[0], + // Ignore non-multipart setting if not supported: + multipart = options.multipart || !$.support.xhrFileUpload, + paramName = options.paramName[0]; + options.headers = options.headers || {}; + if (options.contentRange) { + options.headers['Content-Range'] = options.contentRange; + } + if (!multipart) { + options.headers['Content-Disposition'] = 'attachment; filename="' + + encodeURI(file.name) + '"'; + options.contentType = file.type; + options.data = options.blob || file; + } else if ($.support.xhrFormDataFileUpload) { + if (options.postMessage) { + // window.postMessage does not allow sending FormData + // objects, so we just add the File/Blob objects to + // the formData array and let the postMessage window + // create the FormData object out of this array: + formData = this._getFormData(options); + if (options.blob) { + formData.push({ + name: paramName, + value: options.blob + }); + } else { + $.each(options.files, function (index, file) { + formData.push({ + name: options.paramName[index] || paramName, + value: file + }); + }); + } + } else { + if (options.formData instanceof FormData) { + formData = options.formData; + } else { + formData = new FormData(); + $.each(this._getFormData(options), function (index, field) { + formData.append(field.name, field.value); + }); + } + if (options.blob) { + options.headers['Content-Disposition'] = 'attachment; filename="' + + encodeURI(file.name) + '"'; + formData.append(paramName, options.blob, file.name); + } else { + $.each(options.files, function (index, file) { + // Files are also Blob instances, but some browsers + // (Firefox 3.6) support the File API but not Blobs. + // This check allows the tests to run with + // dummy objects: + if ((window.Blob && Object.prototype.toString.call(file) === '[object Blob]') || + (window.File && Object.prototype.toString.call(file) === '[object File]')) { + formData.append( + options.paramName[index] || paramName, + file, + file.name + ); + } + }); + } + } + options.data = formData; + } + // Blob reference is not needed anymore, free memory: + options.blob = null; + }, + + _initIframeSettings: function (options) { + // Setting the dataType to iframe enables the iframe transport: + options.dataType = 'iframe ' + (options.dataType || ''); + // The iframe transport accepts a serialized array as form data: + options.formData = this._getFormData(options); + // Add redirect url to form data on cross-domain uploads: + if (options.redirect && $('').prop('href', options.url) + .prop('host') !== location.host) { + options.formData.push({ + name: options.redirectParamName || 'redirect', + value: options.redirect + }); + } + }, + + _initDataSettings: function (options) { + if (this._isXHRUpload(options)) { + if (!this._chunkedUpload(options, true)) { + if (!options.data) { + this._initXHRData(options); + } + this._initProgressListener(options); + } + if (options.postMessage) { + // Setting the dataType to postmessage enables the + // postMessage transport: + options.dataType = 'postmessage ' + (options.dataType || ''); + } + } else { + this._initIframeSettings(options, 'iframe'); + } + }, + + _getParamName: function (options) { + var fileInput = $(options.fileInput), + paramName = options.paramName; + if (!paramName) { + paramName = []; + fileInput.each(function () { + var input = $(this), + name = input.prop('name') || 'files[]', + i = (input.prop('files') || [1]).length; + while (i) { + paramName.push(name); + i -= 1; + } + }); + if (!paramName.length) { + paramName = [fileInput.prop('name') || 'files[]']; + } + } else if (!$.isArray(paramName)) { + paramName = [paramName]; + } + return paramName; + }, + + _initFormSettings: function (options) { + // Retrieve missing options from the input field and the + // associated form, if available: + if (!options.form || !options.form.length) { + options.form = $(options.fileInput.prop('form')); + // If the given file input doesn't have an associated form, + // use the default widget file input's form: + if (!options.form.length) { + options.form = $(this.options.fileInput.prop('form')); + } + } + options.paramName = this._getParamName(options); + if (!options.url) { + options.url = options.form.prop('action') || location.href; + } + // The HTTP request method must be "POST" or "PUT": + options.type = (options.type || options.form.prop('method') || '') + .toUpperCase(); + if (options.type !== 'POST' && options.type !== 'PUT' && + options.type !== 'PATCH') { + options.type = 'POST'; + } + if (!options.formAcceptCharset) { + options.formAcceptCharset = options.form.attr('accept-charset'); + } + }, + + _getAJAXSettings: function (data) { + var options = $.extend({}, this.options, data); + this._initFormSettings(options); + this._initDataSettings(options); + return options; + }, + + // jQuery 1.6 doesn't provide .state(), + // while jQuery 1.8+ removed .isRejected() and .isResolved(): + _getDeferredState: function (deferred) { + if (deferred.state) { + return deferred.state(); + } + if (deferred.isResolved()) { + return 'resolved'; + } + if (deferred.isRejected()) { + return 'rejected'; + } + return 'pending'; + }, + + // Maps jqXHR callbacks to the equivalent + // methods of the given Promise object: + _enhancePromise: function (promise) { + promise.success = promise.done; + promise.error = promise.fail; + promise.complete = promise.always; + return promise; + }, + + // Creates and returns a Promise object enhanced with + // the jqXHR methods abort, success, error and complete: + _getXHRPromise: function (resolveOrReject, context, args) { + var dfd = $.Deferred(), + promise = dfd.promise(); + context = context || this.options.context || promise; + if (resolveOrReject === true) { + dfd.resolveWith(context, args); + } else if (resolveOrReject === false) { + dfd.rejectWith(context, args); + } + promise.abort = dfd.promise; + return this._enhancePromise(promise); + }, + + // Adds convenience methods to the callback arguments: + _addConvenienceMethods: function (e, data) { + var that = this; + data.submit = function () { + if (this.state() !== 'pending') { + data.jqXHR = this.jqXHR = + (that._trigger('submit', e, this) !== false) && + that._onSend(e, this); + } + return this.jqXHR || that._getXHRPromise(); + }; + data.abort = function () { + if (this.jqXHR) { + return this.jqXHR.abort(); + } + return that._getXHRPromise(); + }; + data.state = function () { + if (this.jqXHR) { + return that._getDeferredState(this.jqXHR); + } + }; + data.progress = function () { + return this._progress; + }; + data.response = function () { + return this._response; + }; + }, + + // Parses the Range header from the server response + // and returns the uploaded bytes: + _getUploadedBytes: function (jqXHR) { + var range = jqXHR.getResponseHeader('Range'), + parts = range && range.split('-'), + upperBytesPos = parts && parts.length > 1 && + parseInt(parts[1], 10); + return upperBytesPos && upperBytesPos + 1; + }, + + // Uploads a file in multiple, sequential requests + // by splitting the file up in multiple blob chunks. + // If the second parameter is true, only tests if the file + // should be uploaded in chunks, but does not invoke any + // upload requests: + _chunkedUpload: function (options, testOnly) { + var that = this, + file = options.files[0], + fs = file.size, + ub = options.uploadedBytes = options.uploadedBytes || 0, + mcs = options.maxChunkSize || fs, + slice = file.slice || file.webkitSlice || file.mozSlice, + dfd = $.Deferred(), + promise = dfd.promise(), + jqXHR, + upload; + if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) || + options.data) { + return false; + } + if (testOnly) { + return true; + } + if (ub >= fs) { + file.error = 'Uploaded bytes exceed file size'; + return this._getXHRPromise( + false, + options.context, + [null, 'error', file.error] + ); + } + // The chunk upload method: + upload = function () { + // Clone the options object for each chunk upload: + var o = $.extend({}, options), + currentLoaded = o._progress.loaded; + o.blob = slice.call( + file, + ub, + ub + mcs, + file.type + ); + // Store the current chunk size, as the blob itself + // will be dereferenced after data processing: + o.chunkSize = o.blob.size; + // Expose the chunk bytes position range: + o.contentRange = 'bytes ' + ub + '-' + + (ub + o.chunkSize - 1) + '/' + fs; + // Process the upload data (the blob and potential form data): + that._initXHRData(o); + // Add progress listeners for this chunk upload: + that._initProgressListener(o); + jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) || + that._getXHRPromise(false, o.context)) + .done(function (result, textStatus, jqXHR) { + ub = that._getUploadedBytes(jqXHR) || + (ub + o.chunkSize); + // Create a progress event if no final progress event + // with loaded equaling total has been triggered + // for this chunk: + if (o._progress.loaded === currentLoaded) { + that._onProgress($.Event('progress', { + lengthComputable: true, + loaded: ub - o.uploadedBytes, + total: ub - o.uploadedBytes + }), o); + } + options.uploadedBytes = o.uploadedBytes = ub; + o.result = result; + o.textStatus = textStatus; + o.jqXHR = jqXHR; + that._trigger('chunkdone', null, o); + that._trigger('chunkalways', null, o); + if (ub < fs) { + // File upload not yet complete, + // continue with the next chunk: + upload(); + } else { + dfd.resolveWith( + o.context, + [result, textStatus, jqXHR] + ); + } + }) + .fail(function (jqXHR, textStatus, errorThrown) { + o.jqXHR = jqXHR; + o.textStatus = textStatus; + o.errorThrown = errorThrown; + that._trigger('chunkfail', null, o); + that._trigger('chunkalways', null, o); + dfd.rejectWith( + o.context, + [jqXHR, textStatus, errorThrown] + ); + }); + }; + this._enhancePromise(promise); + promise.abort = function () { + return jqXHR.abort(); + }; + upload(); + return promise; + }, + + _beforeSend: function (e, data) { + if (this._active === 0) { + // the start callback is triggered when an upload starts + // and no other uploads are currently running, + // equivalent to the global ajaxStart event: + this._trigger('start'); + // Set timer for global bitrate progress calculation: + this._bitrateTimer = new this._BitrateTimer(); + // Reset the global progress values: + this._progress.loaded = this._progress.total = 0; + this._progress.bitrate = 0; + } + // Make sure the container objects for the .response() and + // .progress() methods on the data object are available + // and reset to their initial state: + this._initResponseObject(data); + this._initProgressObject(data); + data._progress.loaded = data.loaded = data.uploadedBytes || 0; + data._progress.total = data.total = this._getTotal(data.files) || 1; + data._progress.bitrate = data.bitrate = 0; + this._active += 1; + // Initialize the global progress values: + this._progress.loaded += data.loaded; + this._progress.total += data.total; + }, + + _onDone: function (result, textStatus, jqXHR, options) { + var total = options._progress.total, + response = options._response; + if (options._progress.loaded < total) { + // Create a progress event if no final progress event + // with loaded equaling total has been triggered: + this._onProgress($.Event('progress', { + lengthComputable: true, + loaded: total, + total: total + }), options); + } + response.result = options.result = result; + response.textStatus = options.textStatus = textStatus; + response.jqXHR = options.jqXHR = jqXHR; + this._trigger('done', null, options); + }, + + _onFail: function (jqXHR, textStatus, errorThrown, options) { + var response = options._response; + if (options.recalculateProgress) { + // Remove the failed (error or abort) file upload from + // the global progress calculation: + this._progress.loaded -= options._progress.loaded; + this._progress.total -= options._progress.total; + } + response.jqXHR = options.jqXHR = jqXHR; + response.textStatus = options.textStatus = textStatus; + response.errorThrown = options.errorThrown = errorThrown; + this._trigger('fail', null, options); + }, + + _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { + // jqXHRorResult, textStatus and jqXHRorError are added to the + // options object via done and fail callbacks + this._trigger('always', null, options); + }, + + _onSend: function (e, data) { + if (!data.submit) { + this._addConvenienceMethods(e, data); + } + var that = this, + jqXHR, + aborted, + slot, + pipe, + options = that._getAJAXSettings(data), + send = function () { + that._sending += 1; + // Set timer for bitrate progress calculation: + options._bitrateTimer = new that._BitrateTimer(); + jqXHR = jqXHR || ( + ((aborted || that._trigger('send', e, options) === false) && + that._getXHRPromise(false, options.context, aborted)) || + that._chunkedUpload(options) || $.ajax(options) + ).done(function (result, textStatus, jqXHR) { + that._onDone(result, textStatus, jqXHR, options); + }).fail(function (jqXHR, textStatus, errorThrown) { + that._onFail(jqXHR, textStatus, errorThrown, options); + }).always(function (jqXHRorResult, textStatus, jqXHRorError) { + that._onAlways( + jqXHRorResult, + textStatus, + jqXHRorError, + options + ); + that._sending -= 1; + that._active -= 1; + if (options.limitConcurrentUploads && + options.limitConcurrentUploads > that._sending) { + // Start the next queued upload, + // that has not been aborted: + var nextSlot = that._slots.shift(); + while (nextSlot) { + if (that._getDeferredState(nextSlot) === 'pending') { + nextSlot.resolve(); + break; + } + nextSlot = that._slots.shift(); + } + } + if (that._active === 0) { + // The stop callback is triggered when all uploads have + // been completed, equivalent to the global ajaxStop event: + that._trigger('stop'); + } + }); + return jqXHR; + }; + this._beforeSend(e, options); + if (this.options.sequentialUploads || + (this.options.limitConcurrentUploads && + this.options.limitConcurrentUploads <= this._sending)) { + if (this.options.limitConcurrentUploads > 1) { + slot = $.Deferred(); + this._slots.push(slot); + pipe = slot.pipe(send); + } else { + pipe = (this._sequence = this._sequence.pipe(send, send)); + } + // Return the piped Promise object, enhanced with an abort method, + // which is delegated to the jqXHR object of the current upload, + // and jqXHR callbacks mapped to the equivalent Promise methods: + pipe.abort = function () { + aborted = [undefined, 'abort', 'abort']; + if (!jqXHR) { + if (slot) { + slot.rejectWith(options.context, aborted); + } + return send(); + } + return jqXHR.abort(); + }; + return this._enhancePromise(pipe); + } + return send(); + }, + + _onAdd: function (e, data) { + var that = this, + result = true, + options = $.extend({}, this.options, data), + limit = options.limitMultiFileUploads, + paramName = this._getParamName(options), + paramNameSet, + paramNameSlice, + fileSet, + i; + if (!(options.singleFileUploads || limit) || + !this._isXHRUpload(options)) { + fileSet = [data.files]; + paramNameSet = [paramName]; + } else if (!options.singleFileUploads && limit) { + fileSet = []; + paramNameSet = []; + for (i = 0; i < data.files.length; i += limit) { + fileSet.push(data.files.slice(i, i + limit)); + paramNameSlice = paramName.slice(i, i + limit); + if (!paramNameSlice.length) { + paramNameSlice = paramName; + } + paramNameSet.push(paramNameSlice); + } + } else { + paramNameSet = paramName; + } + data.originalFiles = data.files; + $.each(fileSet || data.files, function (index, element) { + var newData = $.extend({}, data); + newData.files = fileSet ? element : [element]; + newData.paramName = paramNameSet[index]; + that._initResponseObject(newData); + that._initProgressObject(newData); + that._addConvenienceMethods(e, newData); + result = that._trigger('add', e, newData); + return result; + }); + return result; + }, + + _replaceFileInput: function (input) { + var inputClone = input.clone(true); + $('
').append(inputClone)[0].reset(); + // Detaching allows to insert the fileInput on another form + // without loosing the file input value: + input.after(inputClone).detach(); + // Avoid memory leaks with the detached file input: + $.cleanData(input.unbind('remove')); + // Replace the original file input element in the fileInput + // elements set with the clone, which has been copied including + // event handlers: + this.options.fileInput = this.options.fileInput.map(function (i, el) { + if (el === input[0]) { + return inputClone[0]; + } + return el; + }); + // If the widget has been initialized on the file input itself, + // override this.element with the file input clone: + if (input[0] === this.element[0]) { + this.element = inputClone; + } + }, + + _handleFileTreeEntry: function (entry, path) { + var that = this, + dfd = $.Deferred(), + errorHandler = function (e) { + if (e && !e.entry) { + e.entry = entry; + } + // Since $.when returns immediately if one + // Deferred is rejected, we use resolve instead. + // This allows valid files and invalid items + // to be returned together in one set: + dfd.resolve([e]); + }, + dirReader; + path = path || ''; + if (entry.isFile) { + if (entry._file) { + // Workaround for Chrome bug #149735 + entry._file.relativePath = path; + dfd.resolve(entry._file); + } else { + entry.file(function (file) { + file.relativePath = path; + dfd.resolve(file); + }, errorHandler); + } + } else if (entry.isDirectory) { + dirReader = entry.createReader(); + dirReader.readEntries(function (entries) { + that._handleFileTreeEntries( + entries, + path + entry.name + '/' + ).done(function (files) { + dfd.resolve(files); + }).fail(errorHandler); + }, errorHandler); + } else { + // Return an empy list for file system items + // other than files or directories: + dfd.resolve([]); + } + return dfd.promise(); + }, + + _handleFileTreeEntries: function (entries, path) { + var that = this; + return $.when.apply( + $, + $.map(entries, function (entry) { + return that._handleFileTreeEntry(entry, path); + }) + ).pipe(function () { + return Array.prototype.concat.apply( + [], + arguments + ); + }); + }, + + _getDroppedFiles: function (dataTransfer) { + dataTransfer = dataTransfer || {}; + var items = dataTransfer.items; + if (items && items.length && (items[0].webkitGetAsEntry || + items[0].getAsEntry)) { + return this._handleFileTreeEntries( + $.map(items, function (item) { + var entry; + if (item.webkitGetAsEntry) { + entry = item.webkitGetAsEntry(); + if (entry) { + // Workaround for Chrome bug #149735: + entry._file = item.getAsFile(); + } + return entry; + } + return item.getAsEntry(); + }) + ); + } + return $.Deferred().resolve( + $.makeArray(dataTransfer.files) + ).promise(); + }, + + _getSingleFileInputFiles: function (fileInput) { + fileInput = $(fileInput); + var entries = fileInput.prop('webkitEntries') || + fileInput.prop('entries'), + files, + value; + if (entries && entries.length) { + return this._handleFileTreeEntries(entries); + } + files = $.makeArray(fileInput.prop('files')); + if (!files.length) { + value = fileInput.prop('value'); + if (!value) { + return $.Deferred().resolve([]).promise(); + } + // If the files property is not available, the browser does not + // support the File API and we add a pseudo File object with + // the input value as name with path information removed: + files = [{name: value.replace(/^.*\\/, '')}]; + } else if (files[0].name === undefined && files[0].fileName) { + // File normalization for Safari 4 and Firefox 3: + $.each(files, function (index, file) { + file.name = file.fileName; + file.size = file.fileSize; + }); + } + return $.Deferred().resolve(files).promise(); + }, + + _getFileInputFiles: function (fileInput) { + if (!(fileInput instanceof $) || fileInput.length === 1) { + return this._getSingleFileInputFiles(fileInput); + } + return $.when.apply( + $, + $.map(fileInput, this._getSingleFileInputFiles) + ).pipe(function () { + return Array.prototype.concat.apply( + [], + arguments + ); + }); + }, + + _onChange: function (e) { + var that = this, + data = { + fileInput: $(e.target), + form: $(e.target.form) + }; + this._getFileInputFiles(data.fileInput).always(function (files) { + data.files = files; + if (that.options.replaceFileInput) { + that._replaceFileInput(data.fileInput); + } + if (that._trigger('change', e, data) !== false) { + that._onAdd(e, data); + } + }); + }, + + _onPaste: function (e) { + var cbd = e.originalEvent.clipboardData, + items = (cbd && cbd.items) || [], + data = {files: []}; + $.each(items, function (index, item) { + var file = item.getAsFile && item.getAsFile(); + if (file) { + data.files.push(file); + } + }); + if (this._trigger('paste', e, data) === false || + this._onAdd(e, data) === false) { + return false; + } + }, + + _onDrop: function (e) { + var that = this, + dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer, + data = {}; + if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { + e.preventDefault(); + } + this._getDroppedFiles(dataTransfer).always(function (files) { + data.files = files; + if (that._trigger('drop', e, data) !== false) { + that._onAdd(e, data); + } + }); + }, + + _onDragOver: function (e) { + var dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer; + if (this._trigger('dragover', e) === false) { + return false; + } + if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1) { + dataTransfer.dropEffect = 'copy'; + e.preventDefault(); + } + }, + + _initEventHandlers: function () { + if (this._isXHRUpload(this.options)) { + this._on(this.options.dropZone, { + dragover: this._onDragOver, + drop: this._onDrop + }); + this._on(this.options.pasteZone, { + paste: this._onPaste + }); + } + this._on(this.options.fileInput, { + change: this._onChange + }); + }, + + _destroyEventHandlers: function () { + this._off(this.options.dropZone, 'dragover drop'); + this._off(this.options.pasteZone, 'paste'); + this._off(this.options.fileInput, 'change'); + }, + + _setOption: function (key, value) { + var refresh = $.inArray(key, this._refreshOptionsList) !== -1; + if (refresh) { + this._destroyEventHandlers(); + } + this._super(key, value); + if (refresh) { + this._initSpecialOptions(); + this._initEventHandlers(); + } + }, + + _initSpecialOptions: function () { + var options = this.options; + if (options.fileInput === undefined) { + options.fileInput = this.element.is('input[type="file"]') ? + this.element : this.element.find('input[type="file"]'); + } else if (!(options.fileInput instanceof $)) { + options.fileInput = $(options.fileInput); + } + if (!(options.dropZone instanceof $)) { + options.dropZone = $(options.dropZone); + } + if (!(options.pasteZone instanceof $)) { + options.pasteZone = $(options.pasteZone); + } + }, + + _create: function () { + var options = this.options; + // Initialize options set via HTML5 data-attributes: + $.extend(options, $(this.element[0].cloneNode(false)).data()); + this._initSpecialOptions(); + this._slots = []; + this._sequence = this._getXHRPromise(true); + this._sending = this._active = 0; + this._initProgressObject(this); + this._initEventHandlers(); + }, + + // This method is exposed to the widget API and allows to query + // the number of active uploads: + active: function () { + return this._active; + }, + + // This method is exposed to the widget API and allows to query + // the widget upload progress. + // It returns an object with loaded, total and bitrate properties + // for the running uploads: + progress: function () { + return this._progress; + }, + + // This method is exposed to the widget API and allows adding files + // using the fileupload API. The data parameter accepts an object which + // must have a files property and can contain additional options: + // .fileupload('add', {files: filesList}); + add: function (data) { + var that = this; + if (!data || this.options.disabled) { + return; + } + if (data.fileInput && !data.files) { + this._getFileInputFiles(data.fileInput).always(function (files) { + data.files = files; + that._onAdd(null, data); + }); + } else { + data.files = $.makeArray(data.files); + this._onAdd(null, data); + } + }, + + // This method is exposed to the widget API and allows sending files + // using the fileupload API. The data parameter accepts an object which + // must have a files or fileInput property and can contain additional options: + // .fileupload('send', {files: filesList}); + // The method returns a Promise object for the file upload call. + send: function (data) { + if (data && !this.options.disabled) { + if (data.fileInput && !data.files) { + var that = this, + dfd = $.Deferred(), + promise = dfd.promise(), + jqXHR, + aborted; + promise.abort = function () { + aborted = true; + if (jqXHR) { + return jqXHR.abort(); + } + dfd.reject(null, 'abort', 'abort'); + return promise; + }; + this._getFileInputFiles(data.fileInput).always( + function (files) { + if (aborted) { + return; + } + data.files = files; + jqXHR = that._onSend(null, data).then( + function (result, textStatus, jqXHR) { + dfd.resolve(result, textStatus, jqXHR); + }, + function (jqXHR, textStatus, errorThrown) { + dfd.reject(jqXHR, textStatus, errorThrown); + } + ); + } + ); + return this._enhancePromise(promise); + } + data.files = $.makeArray(data.files); + if (data.files.length) { + return this._onSend(null, data); + } + } + return this._getXHRPromise(false, data && data.context); + } + + }); + +})); diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.fileupload.min.js b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.fileupload.min.js new file mode 100644 index 000000000..bdf43cc44 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.fileupload.min.js @@ -0,0 +1,2 @@ +(function(n){"use strict";typeof define=="function"&&define.amd?define(["jquery","jquery.ui.widget"],n):n(window.jQuery)})(function(n){"use strict";n.support.xhrFileUpload=!!(window.XMLHttpRequestUpload&&window.FileReader),n.support.xhrFormDataFileUpload=!!window.FormData,n.widget("blueimp.fileupload",{options:{dropZone:n(document),pasteZone:n(document),fileInput:undefined,replaceFileInput:!0,paramName:undefined,singleFileUploads:!0,limitMultiFileUploads:undefined,sequentialUploads:!1,limitConcurrentUploads:undefined,forceIframeTransport:!1,redirect:undefined,redirectParamName:undefined,postMessage:undefined,multipart:!0,maxChunkSize:undefined,uploadedBytes:undefined,recalculateProgress:!0,progressInterval:100,bitrateInterval:500,autoUpload:!0,formData:function(n){return n.serializeArray()},add:function(t,i){(i.autoUpload||i.autoUpload!==!1&&(n(this).data("blueimp-fileupload")||n(this).data("fileupload")).options.autoUpload)&&i.submit()},processData:!1,contentType:!1,cache:!1},_refreshOptionsList:["fileInput","dropZone","pasteZone","multipart","forceIframeTransport"],_BitrateTimer:function(){this.timestamp=Date.now?Date.now():(new Date).getTime(),this.loaded=0,this.bitrate=0,this.getBitrate=function(n,t,i){var r=n-this.timestamp;return(!this.bitrate||!i||r>i)&&(this.bitrate=(t-this.loaded)*(1e3/r)*8,this.loaded=t,this.timestamp=n),this.bitrate}},_isXHRUpload:function(t){return!t.forceIframeTransport&&(!t.multipart&&n.support.xhrFileUpload||n.support.xhrFormDataFileUpload)},_getFormData:function(t){var i;return typeof t.formData=="function"?t.formData(t.form):n.isArray(t.formData)?t.formData:n.type(t.formData)==="object"?(i=[],n.each(t.formData,function(n,t){i.push({name:n,value:t})}),i):[]},_getTotal:function(t){var i=0;return n.each(t,function(n,t){i+=t.size||1}),i},_initProgressObject:function(t){var i={loaded:0,total:0,bitrate:0};t._progress?n.extend(t._progress,i):t._progress=i},_initResponseObject:function(n){var t;if(n._response)for(t in n._response)n._response.hasOwnProperty(t)&&delete n._response[t];else n._response={}},_onProgress:function(n,t){if(n.lengthComputable){var i=Date.now?Date.now():(new Date).getTime(),r;if(t._time&&t.progressInterval&&i-t._time<\/a>").prop("href",t.url).prop("host")!==location.host&&t.formData.push({name:t.redirectParamName||"redirect",value:t.redirect})},_initDataSettings:function(n){this._isXHRUpload(n)?(this._chunkedUpload(n,!0)||(n.data||this._initXHRData(n),this._initProgressListener(n)),n.postMessage&&(n.dataType="postmessage "+(n.dataType||""))):this._initIframeSettings(n,"iframe")},_getParamName:function(t){var r=n(t.fileInput),i=t.paramName;return i?n.isArray(i)||(i=[i]):(i=[],r.each(function(){for(var t=n(this),u=t.prop("name")||"files[]",r=(t.prop("files")||[1]).length;r;)i.push(u),r-=1}),i.length||(i=[r.prop("name")||"files[]"])),i},_initFormSettings:function(t){t.form&&t.form.length||(t.form=n(t.fileInput.prop("form")),t.form.length||(t.form=n(this.options.fileInput.prop("form")))),t.paramName=this._getParamName(t),t.url||(t.url=t.form.prop("action")||location.href),t.type=(t.type||t.form.prop("method")||"").toUpperCase(),t.type!=="POST"&&t.type!=="PUT"&&t.type!=="PATCH"&&(t.type="POST"),t.formAcceptCharset||(t.formAcceptCharset=t.form.attr("accept-charset"))},_getAJAXSettings:function(t){var i=n.extend({},this.options,t);return this._initFormSettings(i),this._initDataSettings(i),i},_getDeferredState:function(n){return n.state?n.state():n.isResolved()?"resolved":n.isRejected()?"rejected":"pending"},_enhancePromise:function(n){return n.success=n.done,n.error=n.fail,n.complete=n.always,n},_getXHRPromise:function(t,i,r){var u=n.Deferred(),f=u.promise();return i=i||this.options.context||f,t===!0?u.resolveWith(i,r):t===!1&&u.rejectWith(i,r),f.abort=u.promise,this._enhancePromise(f)},_addConvenienceMethods:function(n,t){var i=this;t.submit=function(){return this.state()!=="pending"&&(t.jqXHR=this.jqXHR=i._trigger("submit",n,this)!==!1&&i._onSend(n,this)),this.jqXHR||i._getXHRPromise()},t.abort=function(){return this.jqXHR?this.jqXHR.abort():i._getXHRPromise()},t.state=function(){if(this.jqXHR)return i._getDeferredState(this.jqXHR)},t.progress=function(){return this._progress},t.response=function(){return this._response}},_getUploadedBytes:function(n){var i=n.getResponseHeader("Range"),t=i&&i.split("-"),r=t&&t.length>1&&parseInt(t[1],10);return r&&r+1},_chunkedUpload:function(t,i){var u=this,f=t.files[0],e=f.size,r=t.uploadedBytes=t.uploadedBytes||0,c=t.maxChunkSize||e,l=f.slice||f.webkitSlice||f.mozSlice,o=n.Deferred(),s=o.promise(),a,h;return!(this._isXHRUpload(t)&&l&&(r||c=e?(f.error="Uploaded bytes exceed file size",this._getXHRPromise(!1,t.context,[null,"error",f.error])):(h=function(){var i=n.extend({},t),s=i._progress.loaded;i.blob=l.call(f,r,r+c,f.type),i.chunkSize=i.blob.size,i.contentRange="bytes "+r+"-"+(r+i.chunkSize-1)+"/"+e,u._initXHRData(i),u._initProgressListener(i),a=(u._trigger("chunksend",null,i)!==!1&&n.ajax(i)||u._getXHRPromise(!1,i.context)).done(function(f,c,l){r=u._getUploadedBytes(l)||r+i.chunkSize,i._progress.loaded===s&&u._onProgress(n.Event("progress",{lengthComputable:!0,loaded:r-i.uploadedBytes,total:r-i.uploadedBytes}),i),t.uploadedBytes=i.uploadedBytes=r,i.result=f,i.textStatus=c,i.jqXHR=l,u._trigger("chunkdone",null,i),u._trigger("chunkalways",null,i),rr._sending)for(var f=r._slots.shift();f;){if(r._getDeferredState(f)==="pending"){f.resolve();break}f=r._slots.shift()}r._active===0&&r._trigger("stop")})};return(this._beforeSend(t,u),this.options.sequentialUploads||this.options.limitConcurrentUploads&&this.options.limitConcurrentUploads<=this._sending)?(this.options.limitConcurrentUploads>1?(e=n.Deferred(),this._slots.push(e),h=e.pipe(o)):h=this._sequence=this._sequence.pipe(o,o),h.abort=function(){return(s=[undefined,"abort","abort"],!f)?(e&&e.rejectWith(u.context,s),o()):f.abort()},this._enhancePromise(h)):o()},_onAdd:function(t,i){var s=this,l=!0,u=n.extend({},this.options,i),f=u.limitMultiFileUploads,h=this._getParamName(u),e,c,o,r;if((u.singleFileUploads||f)&&this._isXHRUpload(u))if(!u.singleFileUploads&&f)for(o=[],e=[],r=0;r<\/form>").append(i)[0].reset(),t.after(i).detach(),n.cleanData(t.unbind("remove")),this.options.fileInput=this.options.fileInput.map(function(n,r){return r===t[0]?i[0]:r}),t[0]===this.element[0]&&(this.element=i)},_handleFileTreeEntry:function(t,i){var e=this,r=n.Deferred(),u=function(n){n&&!n.entry&&(n.entry=t),r.resolve([n])},f;return i=i||"",t.isFile?t._file?(t._file.relativePath=i,r.resolve(t._file)):t.file(function(n){n.relativePath=i,r.resolve(n)},u):t.isDirectory?(f=t.createReader(),f.readEntries(function(n){e._handleFileTreeEntries(n,i+t.name+"/").done(function(n){r.resolve(n)}).fail(u)},u)):r.resolve([]),r.promise()},_handleFileTreeEntries:function(t,i){var r=this;return n.when.apply(n,n.map(t,function(n){return r._handleFileTreeEntry(n,i)})).pipe(function(){return Array.prototype.concat.apply([],arguments)})},_getDroppedFiles:function(t){t=t||{};var i=t.items;return i&&i.length&&(i[0].webkitGetAsEntry||i[0].getAsEntry)?this._handleFileTreeEntries(n.map(i,function(n){var t;return n.webkitGetAsEntry?(t=n.webkitGetAsEntry(),t&&(t._file=n.getAsFile()),t):n.getAsEntry()})):n.Deferred().resolve(n.makeArray(t.files)).promise()},_getSingleFileInputFiles:function(t){t=n(t);var r=t.prop("webkitEntries")||t.prop("entries"),i,u;if(r&&r.length)return this._handleFileTreeEntries(r);if(i=n.makeArray(t.prop("files")),i.length)i[0].name===undefined&&i[0].fileName&&n.each(i,function(n,t){t.name=t.fileName,t.size=t.fileSize});else{if(u=t.prop("value"),!u)return n.Deferred().resolve([]).promise();i=[{name:u.replace(/^.*\\/,"")}]}return n.Deferred().resolve(i).promise()},_getFileInputFiles:function(t){return!(t instanceof n)||t.length===1?this._getSingleFileInputFiles(t):n.when.apply(n,n.map(t,this._getSingleFileInputFiles)).pipe(function(){return Array.prototype.concat.apply([],arguments)})},_onChange:function(t){var r=this,i={fileInput:n(t.target),form:n(t.target.form)};this._getFileInputFiles(i.fileInput).always(function(n){i.files=n,r.options.replaceFileInput&&r._replaceFileInput(i.fileInput),r._trigger("change",t,i)!==!1&&r._onAdd(t,i)})},_onPaste:function(t){var r=t.originalEvent.clipboardData,u=r&&r.items||[],i={files:[]};return n.each(u,function(n,t){var r=t.getAsFile&&t.getAsFile();r&&i.files.push(r)}),this._trigger("paste",t,i)===!1||this._onAdd(t,i)===!1?!1:void 0},_onDrop:function(n){var r=this,t=n.dataTransfer=n.originalEvent.dataTransfer,i={};t&&t.files&&t.files.length&&n.preventDefault(),this._getDroppedFiles(t).always(function(t){i.files=t,r._trigger("drop",n,i)!==!1&&r._onAdd(n,i)})},_onDragOver:function(t){var i=t.dataTransfer=t.originalEvent.dataTransfer;if(this._trigger("dragover",t)===!1)return!1;i&&n.inArray("Files",i.types)!==-1&&(i.dropEffect="copy",t.preventDefault())},_initEventHandlers:function(){this._isXHRUpload(this.options)&&(this._on(this.options.dropZone,{dragover:this._onDragOver,drop:this._onDrop}),this._on(this.options.pasteZone,{paste:this._onPaste})),this._on(this.options.fileInput,{change:this._onChange})},_destroyEventHandlers:function(){this._off(this.options.dropZone,"dragover drop"),this._off(this.options.pasteZone,"paste"),this._off(this.options.fileInput,"change")},_setOption:function(t,i){var r=n.inArray(t,this._refreshOptionsList)!==-1;r&&this._destroyEventHandlers(),this._super(t,i),r&&(this._initSpecialOptions(),this._initEventHandlers())},_initSpecialOptions:function(){var t=this.options;t.fileInput===undefined?t.fileInput=this.element.is('input[type="file"]')?this.element:this.element.find('input[type="file"]'):t.fileInput instanceof n||(t.fileInput=n(t.fileInput)),t.dropZone instanceof n||(t.dropZone=n(t.dropZone)),t.pasteZone instanceof n||(t.pasteZone=n(t.pasteZone))},_create:function(){var t=this.options;n.extend(t,n(this.element[0].cloneNode(!1)).data()),this._initSpecialOptions(),this._slots=[],this._sequence=this._getXHRPromise(!0),this._sending=this._active=0,this._initProgressObject(this),this._initEventHandlers()},active:function(){return this._active},progress:function(){return this._progress},add:function(t){var i=this;t&&!this.options.disabled&&(t.fileInput&&!t.files?this._getFileInputFiles(t.fileInput).always(function(n){t.files=n,i._onAdd(null,t)}):(t.files=n.makeArray(t.files),this._onAdd(null,t)))},send:function(t){if(t&&!this.options.disabled){if(t.fileInput&&!t.files){var e=this,i=n.Deferred(),r=i.promise(),u,f;return r.abort=function(){return(f=!0,u)?u.abort():(i.reject(null,"abort","abort"),r)},this._getFileInputFiles(t.fileInput).always(function(n){f||(t.files=n,u=e._onSend(null,t).then(function(n,t,r){i.resolve(n,t,r)},function(n,t,r){i.reject(n,t,r)}))}),this._enhancePromise(r)}if(t.files=n.makeArray(t.files),t.files.length)return this._onSend(null,t)}return this._getXHRPromise(!1,t&&t.context)}})}); +//@ sourceMappingURL=jquery.fileupload.min.js.map \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.iframe-transport.js b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.iframe-transport.js new file mode 100644 index 000000000..ed2589506 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.iframe-transport.js @@ -0,0 +1,185 @@ +/* + * jQuery Iframe Transport Plugin 1.6.1 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2011, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint unparam: true, nomen: true */ +/*global define, window, document */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['jquery'], factory); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + + // Helper variable to create unique names for the transport iframes: + var counter = 0; + + // The iframe transport accepts three additional options: + // options.fileInput: a jQuery collection of file input fields + // options.paramName: the parameter name for the file form data, + // overrides the name property of the file input field(s), + // can be a string or an array of strings. + // options.formData: an array of objects with name and value properties, + // equivalent to the return data of .serializeArray(), e.g.: + // [{name: 'a', value: 1}, {name: 'b', value: 2}] + $.ajaxTransport('iframe', function (options) { + if (options.async) { + var form, + iframe, + addParamChar; + return { + send: function (_, completeCallback) { + form = $('
'); + form.attr('accept-charset', options.formAcceptCharset); + addParamChar = /\?/.test(options.url) ? '&' : '?'; + // XDomainRequest only supports GET and POST: + if (options.type === 'DELETE') { + options.url = options.url + addParamChar + '_method=DELETE'; + options.type = 'POST'; + } else if (options.type === 'PUT') { + options.url = options.url + addParamChar + '_method=PUT'; + options.type = 'POST'; + } else if (options.type === 'PATCH') { + options.url = options.url + addParamChar + '_method=PATCH'; + options.type = 'POST'; + } + // javascript:false as initial iframe src + // prevents warning popups on HTTPS in IE6. + // IE versions below IE8 cannot set the name property of + // elements that have already been added to the DOM, + // so we set the name along with the iframe HTML markup: + iframe = $( + '' + ).bind('load', function () { + var fileInputClones, + paramNames = $.isArray(options.paramName) ? + options.paramName : [options.paramName]; + iframe + .unbind('load') + .bind('load', function () { + var response; + // Wrap in a try/catch block to catch exceptions thrown + // when trying to access cross-domain iframe contents: + try { + response = iframe.contents(); + // Google Chrome and Firefox do not throw an + // exception when calling iframe.contents() on + // cross-domain requests, so we unify the response: + if (!response.length || !response[0].firstChild) { + throw new Error(); + } + } catch (e) { + response = undefined; + } + // The complete callback returns the + // iframe content document as response object: + completeCallback( + 200, + 'success', + {'iframe': response} + ); + // Fix for IE endless progress bar activity bug + // (happens on form submits to iframe targets): + $('') + .appendTo(form); + form.remove(); + }); + form + .prop('target', iframe.prop('name')) + .prop('action', options.url) + .prop('method', options.type); + if (options.formData) { + $.each(options.formData, function (index, field) { + $('') + .prop('name', field.name) + .val(field.value) + .appendTo(form); + }); + } + if (options.fileInput && options.fileInput.length && + options.type === 'POST') { + fileInputClones = options.fileInput.clone(); + // Insert a clone for each file input field: + options.fileInput.after(function (index) { + return fileInputClones[index]; + }); + if (options.paramName) { + options.fileInput.each(function (index) { + $(this).prop( + 'name', + paramNames[index] || options.paramName + ); + }); + } + // Appending the file input fields to the hidden form + // removes them from their original location: + form + .append(options.fileInput) + .prop('enctype', 'multipart/form-data') + // enctype must be set as encoding for IE: + .prop('encoding', 'multipart/form-data'); + } + form.submit(); + // Insert the file input fields at their original location + // by replacing the clones with the originals: + if (fileInputClones && fileInputClones.length) { + options.fileInput.each(function (index, input) { + var clone = $(fileInputClones[index]); + $(input).prop('name', clone.prop('name')); + clone.replaceWith(input); + }); + } + }); + form.append(iframe).appendTo(document.body); + }, + abort: function () { + if (iframe) { + // javascript:false as iframe src aborts the request + // and prevents warning popups on HTTPS in IE6. + // concat is used to avoid the "Script URL" JSLint error: + iframe + .unbind('load') + .prop('src', 'javascript'.concat(':false;')); + } + if (form) { + form.remove(); + } + } + }; + } + }); + + // The iframe transport returns the iframe content document as response. + // The following adds converters from iframe to text, json, html, and script: + $.ajaxSetup({ + converters: { + 'iframe text': function (iframe) { + return iframe && $(iframe[0].body).text(); + }, + 'iframe json': function (iframe) { + return iframe && $.parseJSON($(iframe[0].body).text()); + }, + 'iframe html': function (iframe) { + return iframe && $(iframe[0].body).html(); + }, + 'iframe script': function (iframe) { + return iframe && $.globalEval($(iframe[0].body).text()); + } + } + }); + +})); diff --git a/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.iframe-transport.min.js b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.iframe-transport.min.js new file mode 100644 index 000000000..9172a8e1d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.jQuery/Scripts/jquery.iframe-transport.min.js @@ -0,0 +1,2 @@ +(function(n){"use strict";typeof define=="function"&&define.amd?define(["jquery"],n):n(window.jQuery)})(function(n){"use strict";var t=0;n.ajaxTransport("iframe",function(i){if(i.async){var r,u,f;return{send:function(e,o){r=n('
<\/form>'),r.attr("accept-charset",i.formAcceptCharset),f=/\?/.test(i.url)?"&":"?",i.type==="DELETE"?(i.url=i.url+f+"_method=DELETE",i.type="POST"):i.type==="PUT"?(i.url=i.url+f+"_method=PUT",i.type="POST"):i.type==="PATCH"&&(i.url=i.url+f+"_method=PATCH",i.type="POST"),u=n('