Add backload for multiple file upload
@@ -34,7 +34,7 @@ namespace LeafWeb.Core.Tests.Parsers
|
||||
Assert.That(input.ExtraInfo, Is.EqualTo("dear01"));
|
||||
|
||||
var site = input.Site;
|
||||
Assert.That(site.SiteID, Is.EqualTo("Metropolitano"));
|
||||
Assert.That(site.SiteId, Is.EqualTo("Metropolitano"));
|
||||
Assert.That(site.Latitude, Is.EqualTo(8.98333));
|
||||
Assert.That(site.Longitude, Is.EqualTo(-79.55));
|
||||
Assert.That(site.Elevation, Is.Null);
|
||||
@@ -141,7 +141,7 @@ namespace LeafWeb.Core.Tests.Parsers
|
||||
{
|
||||
var dir = @"C:\Users\poprhythm\Documents\code\LeafWeb\Notes\leafweb database work\newcurves\RemovableDisk\curves";
|
||||
var files = Directory.GetFiles(dir, "*.csv").Select(f => new FileInfo(f)).ToList();
|
||||
var leafInputs = new List<LeafInput>();
|
||||
var leafInputs = new List<LeafInputInfo>();
|
||||
var num = 1;
|
||||
foreach (var file in files)
|
||||
{
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
<Compile Include="Models\CntrlComparisonPhotosyntheticInfo.cs" />
|
||||
<Compile Include="Models\FluxnetSite.cs" />
|
||||
<Compile Include="Models\LeafInput.cs" />
|
||||
<Compile Include="Models\LeafInputInfo.cs" />
|
||||
<Compile Include="Models\LeafInputData.cs" />
|
||||
<Compile Include="Models\LeafInputFile.cs" />
|
||||
<Compile Include="Models\LeafInputPhotosynthetic.cs" />
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
public class FluxnetSite
|
||||
{
|
||||
public string FluxnetId { get; set; }
|
||||
|
||||
public string SiteName { get; set; }
|
||||
|
||||
public string Country { get; set; }
|
||||
|
||||
public string LandUnit { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Descriptive information about the investigator,
|
||||
/// contact information, the site,the sample leaf and its general environmental condition
|
||||
/// </summary>
|
||||
public class LeafInput
|
||||
{
|
||||
[Key]
|
||||
public string LeafInputId { get; set; }
|
||||
public int LeafInputId { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
public virtual IEnumerable<LeafInputFile> LeafInputFiles { get; set; }
|
||||
|
||||
[ParseInfo(1, exampleValue: "First and last name")]
|
||||
public string InvestigatorName { get; set; }
|
||||
[Required(ErrorMessage = "Name required")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[ParseInfo(2, exampleValue: "Your email / mail addresses")]
|
||||
public string ContactInformation { get; set; }
|
||||
[Required(ErrorMessage = "An email address is required")]
|
||||
public string Email { get; set; }
|
||||
|
||||
[ParseInfo(3, alternateTitle: "Site name in full", exampleValue: "Your site's identifier / name")]
|
||||
public string SiteName { get; set; }
|
||||
[Required(ErrorMessage = "A unique identifier is required")]
|
||||
public string Identifier { get; set; }
|
||||
|
||||
[ParseInfo(4, exampleValue: "Mixed forest / grasslands / croplands/ etc")]
|
||||
public string VegetationType { get; set; }
|
||||
[Required(ErrorMessage = "")]
|
||||
public string SiteId { get; set; }
|
||||
|
||||
[ParseInfo(5, exampleValue: "Soil type at your site")]
|
||||
public string SoilType { get; set; }
|
||||
|
||||
[ParseInfo(6, exampleValue: "List of major species at the site")]
|
||||
public string MajorSpecies { get; set; }
|
||||
|
||||
[ParseInfo(7,
|
||||
alternateTitle: "Sample leaf light environment",
|
||||
exampleValue: "The general light environment in which the leaf is in (e.g. heavily shaded from above)")]
|
||||
public string SampleLeafLightEnv { get; set; }
|
||||
|
||||
[ParseInfo(8, exampleValue: "Indicate whether there is water stress at the time of sampling")]
|
||||
public string WaterStressAssessment { get; set; }
|
||||
|
||||
[ParseInfo(9, exampleValue: "For example - Licor-6400")]
|
||||
public string InstrumentUsed { get; set; }
|
||||
|
||||
[ParseInfo(10, exampleValue: "Any extra information you feel would be helpful to put the sampled leaf in context")]
|
||||
public string ExtraInfo { get; set; }
|
||||
|
||||
public virtual LeafInputSite Site { get; set; }
|
||||
public virtual LeafInputPhotosynthetic Photosynthetic { get; set; }
|
||||
public virtual IEnumerable<LeafInputData> Data { get; set; }
|
||||
[DataType(DataType.Date)]
|
||||
[Required]
|
||||
public DateTime Created { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
@@ -9,6 +8,11 @@ namespace LeafWeb.Core.Models
|
||||
/// </summary>
|
||||
public class LeafInputData
|
||||
{
|
||||
[Key]
|
||||
public int LeafInputDataId { get; set; }
|
||||
|
||||
public virtual LeafInputInfo LeafInputInfo { get; set; }
|
||||
|
||||
public int ListOrder { get; set; }
|
||||
|
||||
/// <summary>the data point No.</summary>
|
||||
@@ -140,7 +144,5 @@ namespace LeafWeb.Core.Models
|
||||
/// <summary>atmospheric O2 partial pressure</summary>
|
||||
[ParseInfo(31, units: "Pa")]
|
||||
public double? OxygenPress { get; set; }
|
||||
|
||||
public virtual LeafInput LeafInput { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,14 @@ namespace LeafWeb.Core.Models
|
||||
public class LeafInputFile
|
||||
{
|
||||
[Key]
|
||||
public string LeafInputId { get; set; }
|
||||
public byte[] File { get; set; }
|
||||
public int LeafInputFileId { get; set; }
|
||||
|
||||
public virtual LeafInput LeafInput { get; set; }
|
||||
|
||||
public virtual LeafInputInfo LeafInputInfo { get; set; }
|
||||
|
||||
public string Filename { get; set; }
|
||||
|
||||
public byte[] Contents { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Descriptive information about the investigator,
|
||||
/// contact information, the site,the sample leaf and its general environmental condition
|
||||
/// </summary>
|
||||
public class LeafInputInfo
|
||||
{
|
||||
[Key]
|
||||
public int LeafInputInfoId { get; set; }
|
||||
|
||||
public virtual LeafInputSite Site { get; set; }
|
||||
public virtual LeafInputPhotosynthetic Photosynthetic { get; set; }
|
||||
public virtual IEnumerable<LeafInputData> Data { get; set; }
|
||||
|
||||
[ParseInfo(1, exampleValue: "First and last name")]
|
||||
public string InvestigatorName { get; set; }
|
||||
|
||||
[ParseInfo(2, exampleValue: "Your email / mail addresses")]
|
||||
public string ContactInformation { get; set; }
|
||||
|
||||
[ParseInfo(3, alternateTitle: "Site name in full", exampleValue: "Your site's identifier / name")]
|
||||
public string SiteName { get; set; }
|
||||
|
||||
[ParseInfo(4, exampleValue: "Mixed forest / grasslands / croplands/ etc")]
|
||||
public string VegetationType { get; set; }
|
||||
|
||||
[ParseInfo(5, exampleValue: "Soil type at your site")]
|
||||
public string SoilType { get; set; }
|
||||
|
||||
[ParseInfo(6, exampleValue: "List of major species at the site")]
|
||||
public string MajorSpecies { get; set; }
|
||||
|
||||
[ParseInfo(7,
|
||||
alternateTitle: "Sample leaf light environment",
|
||||
exampleValue: "The general light environment in which the leaf is in (e.g. heavily shaded from above)")]
|
||||
public string SampleLeafLightEnv { get; set; }
|
||||
|
||||
[ParseInfo(8, exampleValue: "Indicate whether there is water stress at the time of sampling")]
|
||||
public string WaterStressAssessment { get; set; }
|
||||
|
||||
[ParseInfo(9, exampleValue: "For example - Licor-6400")]
|
||||
public string InstrumentUsed { get; set; }
|
||||
|
||||
[ParseInfo(10, exampleValue: "Any extra information you feel would be helpful to put the sampled leaf in context")]
|
||||
public string ExtraInfo { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using LeafWeb.Core.Parsers;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
@@ -8,6 +9,11 @@ namespace LeafWeb.Core.Models
|
||||
/// </summary>
|
||||
public class LeafInputPhotosynthetic
|
||||
{
|
||||
[Key]
|
||||
public int LeafInputPhotosyntheticId { get; set; }
|
||||
|
||||
public virtual LeafInputInfo LeafInputInfo { get; set; }
|
||||
|
||||
/// <summary>chloroplastic CO2 photocompensation point</summary>
|
||||
/// <remarks>must be positive</remarks>
|
||||
[ParseInfo(1, alternateTitle:"Gamma*", units: "Pa")]
|
||||
@@ -36,7 +42,5 @@ namespace LeafWeb.Core.Models
|
||||
/// <summary>internal (also known as mesophyll) conductance</summary>
|
||||
[ParseInfo(6, units: "umol/m2/s/Pa")]
|
||||
public double gi { get; set; }
|
||||
|
||||
public virtual LeafInput LeafInput { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using LeafWeb.Core.Parsers;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using LeafWeb.Core.Parsers;
|
||||
using LeafWeb.Core.Utility;
|
||||
|
||||
namespace LeafWeb.Core.Models
|
||||
@@ -8,10 +9,15 @@ namespace LeafWeb.Core.Models
|
||||
/// </summary>
|
||||
public class LeafInputSite
|
||||
{
|
||||
[Key]
|
||||
public int LeafInputSiteId { get; set; }
|
||||
|
||||
public virtual LeafInputInfo LeafInputInfo { get; set; }
|
||||
|
||||
/// <summary>Site identifier</summary>
|
||||
/// <remarks>do not leave blank between letters</remarks>
|
||||
[ParseInfo(1)]
|
||||
public string SiteID { get; set; }
|
||||
public string SiteId { get; set; }
|
||||
|
||||
/// <summary>Site latitude, northern hermisphere positive</summary>
|
||||
[ParseInfo(2, units:"degrees")]
|
||||
@@ -92,6 +98,5 @@ namespace LeafWeb.Core.Models
|
||||
|
||||
// DataType,TissueArea,TissueMass,Fo'_or_Fo,Fm'_or_Fm,Fs,MeasLight
|
||||
|
||||
public virtual LeafInput LeafInput { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,13 @@ namespace LeafWeb.Core.Parsers
|
||||
{
|
||||
}
|
||||
|
||||
public LeafInput Parse()
|
||||
public LeafInputInfo Parse()
|
||||
{
|
||||
// First 10 lines
|
||||
var leafInput = ParseLeafInput();
|
||||
leafInput.FileName = CsvFile.Name;
|
||||
|
||||
// filename will be stored in LeafInputFile
|
||||
//leafInput.FileName = CsvFile.Name;
|
||||
|
||||
// Next 3 (Header, Units, and Values)
|
||||
leafInput.Site = ParseLeafInputSite();
|
||||
@@ -31,7 +33,7 @@ namespace LeafWeb.Core.Parsers
|
||||
return leafInput;
|
||||
}
|
||||
|
||||
private LeafInput ParseLeafInput()
|
||||
private LeafInputInfo ParseLeafInput()
|
||||
{
|
||||
var items = new List<string>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
@@ -44,7 +46,7 @@ namespace LeafWeb.Core.Parsers
|
||||
throw new ParseException("Could not read first field on line number " + CsvReader.Row);
|
||||
items.Add(field);
|
||||
}
|
||||
return ParsedObjectFactory<LeafInput>.Create(items.ToArray());
|
||||
return ParsedObjectFactory<LeafInputInfo>.Create(items.ToArray());
|
||||
}
|
||||
|
||||
private LeafInputSite ParseLeafInputSite()
|
||||
@@ -109,7 +111,7 @@ namespace LeafWeb.Core.Parsers
|
||||
return ParsedObjectFactory<LeafInputData>.Create(titles, valueArrays.ToArray());
|
||||
}
|
||||
|
||||
public static void ExportCsv(string filename, IEnumerable<LeafInput> leafInputs)
|
||||
public static void ExportCsv(string filename, IEnumerable<LeafInputInfo> leafInputs)
|
||||
{
|
||||
using (var textWriter = new StreamWriter(filename))
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Web.Optimization;
|
||||
using Backload.Bundles;using System.Web.Optimization;
|
||||
|
||||
namespace LeafWeb.Web.App_Start
|
||||
{
|
||||
@@ -7,6 +7,9 @@ namespace LeafWeb.Web.App_Start
|
||||
// For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
|
||||
public static void RegisterBundles(BundleCollection bundles)
|
||||
{
|
||||
// Add or remove this line for the bundeling feature
|
||||
BackloadBundles.RegisterBundles(bundles);
|
||||
|
||||
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
|
||||
"~/scripts/jquery-{version}.js"));
|
||||
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
using Backload.Configuration;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using System.Web.Optimization;
|
||||
|
||||
namespace Backload.Bundles
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Registers bundles for client side scripts and styles. This is an optional feature.
|
||||
/// </summary>
|
||||
public class BackloadBundles
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Registers bundles for the client side scripts and styles
|
||||
/// </summary>
|
||||
/// <param name="bundles">A BundleCollection instance</param>
|
||||
/// <remarks>This is optional. The Backload component does not need bundeling internally.</remarks>
|
||||
public static void RegisterBundles(BundleCollection bundles)
|
||||
{
|
||||
// Default path to the client side files
|
||||
string vendor = "blueimp";
|
||||
string plugin = "fileupload";
|
||||
string jsroot = "~/Backload/Client";
|
||||
string cssroot = "~/Backload/Client";
|
||||
string jsvendor = string.Empty;
|
||||
string cssvendor = string.Empty;
|
||||
string jsplugin = string.Empty;
|
||||
string cssplugin = string.Empty;
|
||||
|
||||
|
||||
// Note: Comment this section in, if you use backload with a different (not default) path to the client files
|
||||
#region Get the path to the client side scripts and styles from the configuration file
|
||||
try
|
||||
{
|
||||
Backload.Configuration.Bundles bundle = new Backload.Configuration.Bundles();
|
||||
jsroot = Backload.Configuration.Bundles.ClientScripts;
|
||||
cssroot = Backload.Configuration.Bundles.ClientStyles;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region Bundles for the jQuery File Upload Plugin
|
||||
|
||||
// Bundle registration starts here
|
||||
jsvendor = string.Format("{0}/{1}/", jsroot, vendor);
|
||||
jsplugin = string.Format("{0}{1}/js/", jsvendor, plugin);
|
||||
cssvendor = string.Format("{0}/{1}/", cssroot, vendor);
|
||||
cssplugin = string.Format("{0}{1}/css/", cssvendor, plugin);
|
||||
|
||||
|
||||
|
||||
#region jQuery File Upload Plugin: Basic theme (Bootstrap)
|
||||
|
||||
string[] scripts = new string[] {
|
||||
jsplugin + "vendor/jquery.ui.widget.js",
|
||||
jsplugin + "jquery.iframe-transport.js",
|
||||
jsplugin + "jquery.fileupload.js",
|
||||
jsplugin + "themes/jquery.fileupload-themes.js" };
|
||||
|
||||
string[] styles = new string[] {
|
||||
cssplugin + "jquery.fileupload.css" };
|
||||
|
||||
|
||||
bundles.Add(new ScriptBundle("~/backload/blueimp/bootstrap/Basic").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/backload/blueimp/bootstrap/Basic/css").Include(styles));
|
||||
|
||||
// The following virtual path is for backward compatibility only and can be removed
|
||||
bundles.Add(new ScriptBundle("~/bundles/fileUpload/bootstrap/Basic/js").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/bundles/fileUpload/bootstrap/Basic/css").Include(styles));
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region jQuery File Upload Plugin: Basic Plus (Bootstrap)
|
||||
|
||||
scripts = new string[] {
|
||||
jsvendor + "loadimage/js/load-image.all.min.js",
|
||||
jsvendor + "blob/js/canvas-to-blob.min.js",
|
||||
jsplugin + "vendor/jquery.ui.widget.js",
|
||||
jsplugin + "jquery.iframe-transport.js",
|
||||
jsplugin + "jquery.fileupload.js",
|
||||
jsplugin + "jquery.fileupload-process.js",
|
||||
jsplugin + "jquery.fileupload-image.js",
|
||||
jsplugin + "jquery.fileupload-audio.js",
|
||||
jsplugin + "jquery.fileupload-video.js",
|
||||
jsplugin + "jquery.fileupload-validate.js",
|
||||
jsplugin + "themes/jquery.fileupload-themes.js" };
|
||||
|
||||
styles = new string[] {
|
||||
cssplugin + "jquery.fileupload.css" };
|
||||
|
||||
|
||||
bundles.Add(new ScriptBundle("~/backload/blueimp/bootstrap/BasicPlus").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/backload/blueimp/bootstrap/BasicPlus/css").Include(styles));
|
||||
|
||||
// The following virtual path is for backward compatibility only and can be removed
|
||||
bundles.Add(new ScriptBundle("~/bundles/fileUpload/bootstrap/BasicPlus/js").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/bundles/fileUpload/bootstrap/BasicPlus/css").Include(styles));
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region jQuery File Upload Plugin: Basic Plus UI (Bootstrap)
|
||||
|
||||
scripts = new string[] {
|
||||
jsvendor + "templates/js/tmpl.min.js",
|
||||
jsvendor + "loadimage/js/load-image.all.min.js",
|
||||
jsvendor + "blob/js/canvas-to-blob.min.js",
|
||||
jsvendor + "gallery/js/jquery.blueimp-gallery.min.js",
|
||||
jsplugin + "vendor/jquery.ui.widget.js",
|
||||
jsplugin + "jquery.iframe-transport.js",
|
||||
jsplugin + "jquery.fileupload.js",
|
||||
jsplugin + "jquery.fileupload-process.js",
|
||||
jsplugin + "jquery.fileupload-image.js",
|
||||
jsplugin + "jquery.fileupload-audio.js",
|
||||
jsplugin + "jquery.fileupload-video.js",
|
||||
jsplugin + "jquery.fileupload-validate.js",
|
||||
jsplugin + "jquery.fileupload-ui.js",
|
||||
jsplugin + "themes/jquery.fileupload-themes.js" };
|
||||
|
||||
styles = new string[] {
|
||||
cssvendor + "gallery/css/blueimp-gallery.min.css",
|
||||
cssplugin + "jquery.fileupload.css",
|
||||
cssplugin + "jquery.fileupload-ui.css" };
|
||||
|
||||
|
||||
bundles.Add(new ScriptBundle("~/backload/blueimp/bootstrap/BasicPlusUI").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/backload/blueimp/bootstrap/BasicPlusUI/css").Include(styles));
|
||||
|
||||
// The following virtual path is for backward compatibility only and can be removed
|
||||
bundles.Add(new ScriptBundle("~/bundles/fileUpload/bootstrap/BasicPlusUI/js").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/bundles/fileUpload/bootstrap/BasicPlusUI/css").Include(styles));
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region jQuery File Upload Plugin: AngularJS theme
|
||||
|
||||
scripts = new string[] {
|
||||
jsvendor + "loadimage/js/load-image.all.min.js",
|
||||
jsvendor + "blob/js/canvas-to-blob.min.js",
|
||||
jsvendor + "gallery/js/jquery.blueimp-gallery.min.js",
|
||||
jsplugin + "vendor/jquery.ui.widget.js",
|
||||
jsplugin + "jquery.iframe-transport.js",
|
||||
jsplugin + "jquery.fileupload.js",
|
||||
jsplugin + "jquery.fileupload-process.js",
|
||||
jsplugin + "jquery.fileupload-image.js",
|
||||
jsplugin + "jquery.fileupload-audio.js",
|
||||
jsplugin + "jquery.fileupload-video.js",
|
||||
jsplugin + "jquery.fileupload-validate.js",
|
||||
jsplugin + "jquery.fileupload-angular.js" };
|
||||
|
||||
styles = new string[] {
|
||||
cssvendor + "gallery/css/blueimp-gallery.min.css",
|
||||
cssplugin + "jquery.fileupload.css",
|
||||
cssplugin + "jquery.fileupload-ui.css" };
|
||||
|
||||
|
||||
bundles.Add(new ScriptBundle("~/backload/blueimp/angularjs").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/backload/blueimp/angularjs/css").Include(styles));
|
||||
|
||||
// The following virtual path is for backward compatibility only and can be removed
|
||||
bundles.Add(new ScriptBundle("~/bundles/fileUpload/angularjs/js").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/bundles/fileUpload/angularjs/css").Include(styles));
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region jQuery File Upload Plugin: jQueryUI theme
|
||||
|
||||
scripts = new string[] {
|
||||
jsvendor + "templates/js/tmpl.min.js",
|
||||
jsvendor + "loadimage/js/load-image.all.min.js",
|
||||
jsvendor + "blob/js/canvas-to-blob.min.js",
|
||||
jsvendor + "gallery/js/jquery.blueimp-gallery.min.js",
|
||||
jsplugin + "jquery.iframe-transport.js",
|
||||
jsplugin + "jquery.fileupload.js",
|
||||
jsplugin + "jquery.fileupload-process.js",
|
||||
jsplugin + "jquery.fileupload-image.js",
|
||||
jsplugin + "jquery.fileupload-audio.js",
|
||||
jsplugin + "jquery.fileupload-video.js",
|
||||
jsplugin + "jquery.fileupload-validate.js",
|
||||
jsplugin + "jquery.fileupload-ui.js",
|
||||
jsplugin + "jquery.fileupload-jquery-ui.js" };
|
||||
|
||||
styles = new string[] {
|
||||
cssvendor + "gallery/css/blueimp-gallery.min.css",
|
||||
cssplugin + "jquery.fileupload.css",
|
||||
cssplugin + "jquery.fileupload-ui.css" };
|
||||
|
||||
|
||||
bundles.Add(new ScriptBundle("~/backload/blueimp/jqueryui").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/backload/blueimp/jqueryui/css").Include(styles));
|
||||
|
||||
// The following virtual path is for backward compatibility only and can be removed
|
||||
bundles.Add(new ScriptBundle("~/bundles/fileupload/jqueryui/BasicPlusUI/js").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/bundles/fileupload/jqueryui/BasicPlusUI/css").Include(styles));
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region Fine Uploader
|
||||
|
||||
vendor = "widen";
|
||||
plugin = "fineuploader";
|
||||
|
||||
// Fine Uploader from Widen Enterprises
|
||||
jsvendor = string.Format("{0}/{1}/", jsroot, vendor);
|
||||
jsplugin = string.Format("{0}{1}/js/", jsvendor, plugin);
|
||||
cssvendor = string.Format("{0}/{1}/", cssroot, vendor);
|
||||
cssplugin = string.Format("{0}{1}/", cssvendor, plugin);
|
||||
|
||||
|
||||
// Simple and default theme
|
||||
scripts = new string[] {
|
||||
jsplugin + "fine-uploader.min.js" };
|
||||
|
||||
styles = new string[] {
|
||||
cssplugin + "fine-uploader-new.min.css" };
|
||||
|
||||
bundles.Add(new ScriptBundle("~/backload/widen/fineuploader/simple").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/backload/widen/fineuploader/simple/css").Include(styles));
|
||||
|
||||
|
||||
// Gallery theme
|
||||
styles = new string[] {
|
||||
cssplugin + "fine-uploader-gallery.min.css",
|
||||
cssplugin + "fine-uploader-new.min.css" };
|
||||
|
||||
bundles.Add(new ScriptBundle("~/backload/widen/fineuploader/gallery").Include(scripts));
|
||||
bundles.Add(new StyleBundle("~/backload/widen/fineuploader/gallery/css").Include(styles));
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region PlUpload
|
||||
|
||||
vendor = "moxie";
|
||||
plugin = "plupload";
|
||||
|
||||
// Fine Uploader from Widen Enterprises
|
||||
jsvendor = string.Format("{0}/{1}/", jsroot, vendor);
|
||||
jsplugin = string.Format("{0}{1}/js/", jsvendor, plugin);
|
||||
cssplugin = jsplugin;
|
||||
|
||||
|
||||
// Simple theme
|
||||
scripts = new string[] {
|
||||
jsplugin + "plupload.full.min.js" };
|
||||
|
||||
bundles.Add(new ScriptBundle("~/backload/moxie/plupload/simple").Include(scripts));
|
||||
|
||||
|
||||
// UI theme. We need to order the files, otherwise System.Web.Optimization produces a false order
|
||||
scripts = new string[] {
|
||||
jsplugin + "plupload.full.min.js",
|
||||
jsplugin + "jquery.ui.plupload/jquery.ui.plupload.min.js" };
|
||||
|
||||
ScriptBundle scriptBundle = (ScriptBundle)new ScriptBundle("~/backload/moxie/plupload/ui").Include(scripts);
|
||||
BackloadBundleOrderer orderer = new BackloadBundleOrderer();
|
||||
scriptBundle.Orderer = orderer;
|
||||
|
||||
styles = new string[] {
|
||||
cssplugin + "jquery.ui.plupload/css/jquery.ui.plupload.css" };
|
||||
|
||||
bundles.Add(scriptBundle);
|
||||
bundles.Add(new StyleBundle("~/backload/moxie/plupload/ui/css").Include(styles));
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region BackloadBundleOrderer
|
||||
|
||||
/// <summary>
|
||||
/// Orders the scripts in the scripts like we added them.
|
||||
/// </summary>
|
||||
private class BackloadBundleOrderer : IBundleOrderer
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Old IBundleOrderer interface
|
||||
/// </summary>
|
||||
/// <param name="context">BundleContext</param>
|
||||
/// <param name="files">IEnumerable</param>
|
||||
/// <returns>Ordered files</returns>
|
||||
public IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files)
|
||||
{
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// New IBundleOrderer interface
|
||||
/// </summary>
|
||||
/// <param name="context">BundleContext</param>
|
||||
/// <param name="files">IEnumerable</param>
|
||||
/// <returns>Ordered files</returns>
|
||||
public IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files)
|
||||
{
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){"use strict";var b=a.HTMLCanvasElement&&a.HTMLCanvasElement.prototype,c=a.Blob&&function(){try{return Boolean(new Blob)}catch(a){return!1}}(),d=c&&a.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(a){return!1}}(),e=a.BlobBuilder||a.WebKitBlobBuilder||a.MozBlobBuilder||a.MSBlobBuilder,f=(c||e)&&a.atob&&a.ArrayBuffer&&a.Uint8Array&&function(a){var b,f,g,h,i,j;for(b=a.split(",")[0].indexOf("base64")>=0?atob(a.split(",")[1]):decodeURIComponent(a.split(",")[1]),f=new ArrayBuffer(b.length),g=new Uint8Array(f),h=0;h<b.length;h+=1)g[h]=b.charCodeAt(h);return i=a.split(",")[0].split(":")[1].split(";")[0],c?new Blob([d?g:f],{type:i}):(j=new e,j.append(f),j.getBlob(i))};a.HTMLCanvasElement&&!b.toBlob&&(b.mozGetAsFile?b.toBlob=function(a,c,d){d&&b.toDataURL&&f?a(f(this.toDataURL(c,d))):a(this.mozGetAsFile("blob",c))}:b.toDataURL&&f&&(b.toBlob=function(a,b,c){a(f(this.toDataURL(b,c)))})),"function"==typeof define&&define.amd?define(function(){return f}):a.dataURLtoBlob=f}(this);
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "blueimp-canvas-to-blob",
|
||||
"version": "2.1.2",
|
||||
"title": "JavaScript Canvas to Blob",
|
||||
"description": "JavaScript Canvas to Blob is a function to convert canvas elements into Blob objects.",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"canvas",
|
||||
"blob",
|
||||
"convert",
|
||||
"conversion"
|
||||
],
|
||||
"homepage": "https://github.com/blueimp/JavaScript-Canvas-to-Blob",
|
||||
"author": {
|
||||
"name": "Sebastian Tschan",
|
||||
"url": "https://blueimp.net"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Sebastian Tschan",
|
||||
"url": "https://blueimp.net"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/blueimp/JavaScript-Canvas-to-Blob.git"
|
||||
},
|
||||
"bugs": "https://github.com/blueimp/JavaScript-Canvas-to-Blob/issues",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://www.opensource.org/licenses/MIT"
|
||||
}
|
||||
],
|
||||
"main": "./js/canvas-to-blob.js",
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-contrib-uglify": "~0.2.7",
|
||||
"grunt-contrib-jshint": "~0.7.1",
|
||||
"grunt-bump-build-git": "~1.0.0",
|
||||
"grunt-mocha": "~0.4.1",
|
||||
"expect.js": "0.2.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
/*
|
||||
* jQuery File Upload Plugin postMessage API 1.2.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
|
||||
*/
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>jQuery File Upload Plugin postMessage API</title>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
/*jslint unparam: true, regexp: true */
|
||||
/*global $, Blob, FormData, location */
|
||||
'use strict';
|
||||
var origin = /^http:\/\/example.org/,
|
||||
target = new RegExp('^(http(s)?:)?\\/\\/' + location.host + '\\/');
|
||||
$(window).on('message', function (e) {
|
||||
e = e.originalEvent;
|
||||
var s = e.data,
|
||||
xhr = $.ajaxSettings.xhr(),
|
||||
f;
|
||||
if (!origin.test(e.origin)) {
|
||||
throw new Error('Origin "' + e.origin + '" does not match ' + origin);
|
||||
}
|
||||
if (!target.test(e.data.url)) {
|
||||
throw new Error('Target "' + e.data.url + '" does not match ' + target);
|
||||
}
|
||||
$(xhr.upload).on('progress', function (ev) {
|
||||
ev = ev.originalEvent;
|
||||
e.source.postMessage({
|
||||
id: s.id,
|
||||
type: ev.type,
|
||||
timeStamp: ev.timeStamp,
|
||||
lengthComputable: ev.lengthComputable,
|
||||
loaded: ev.loaded,
|
||||
total: ev.total
|
||||
}, e.origin);
|
||||
});
|
||||
s.xhr = function () {
|
||||
return xhr;
|
||||
};
|
||||
if (!(s.data instanceof Blob)) {
|
||||
f = new FormData();
|
||||
$.each(s.data, function (i, v) {
|
||||
f.append(v.name, v.value);
|
||||
});
|
||||
s.data = f;
|
||||
}
|
||||
$.ajax(s).always(function (result, statusText, jqXHR) {
|
||||
if (!jqXHR.done) {
|
||||
jqXHR = result;
|
||||
result = null;
|
||||
}
|
||||
e.source.postMessage({
|
||||
id: s.id,
|
||||
status: jqXHR.status,
|
||||
statusText: statusText,
|
||||
result: result,
|
||||
headers: jqXHR.getAllResponseHeaders()
|
||||
}, e.origin);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
/*
|
||||
* jQuery Iframe Transport Plugin Redirect Page 2.0.1
|
||||
* 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
|
||||
*/
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>jQuery Iframe Transport Plugin Redirect Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
document.body.innerText=document.body.textContent=decodeURIComponent(window.location.search.slice(1));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
@charset "UTF-8";
|
||||
/*
|
||||
* jQuery File Upload Plugin NoScript CSS 1.2.0
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
.fileinput-button input {
|
||||
position: static;
|
||||
opacity: 1;
|
||||
filter: none;
|
||||
font-size: inherit;
|
||||
direction: inherit;
|
||||
}
|
||||
.fileinput-button span {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
@charset "UTF-8";
|
||||
/*
|
||||
* jQuery File Upload UI Plugin NoScript CSS 8.8.5
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2012, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
.fileinput-button i,
|
||||
.fileupload-buttonbar .delete,
|
||||
.fileupload-buttonbar .toggle {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
@charset "UTF-8";
|
||||
/*
|
||||
* jQuery File Upload UI Plugin CSS 9.0.0
|
||||
* 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
|
||||
*/
|
||||
|
||||
.fileupload-buttonbar .btn,
|
||||
.fileupload-buttonbar .toggle {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.progress-animated .progress-bar,
|
||||
.progress-animated .bar {
|
||||
background: url("../img/progressbar.gif") !important;
|
||||
filter: none;
|
||||
}
|
||||
.fileupload-process {
|
||||
float: right;
|
||||
display: none;
|
||||
}
|
||||
.fileupload-processing .fileupload-process,
|
||||
.files .processing .preview {
|
||||
display: block;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: url("../img/loading.gif") center no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
.files audio,
|
||||
.files video {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.fileupload-buttonbar .toggle,
|
||||
.files .toggle,
|
||||
.files .btn span {
|
||||
display: none;
|
||||
}
|
||||
.files .name {
|
||||
width: 80px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.files audio,
|
||||
.files video {
|
||||
max-width: 80px;
|
||||
}
|
||||
.files img,
|
||||
.files canvas {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
@charset "UTF-8";
|
||||
/*
|
||||
* jQuery File Upload Plugin CSS 1.3.0
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
.fileinput-button {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
}
|
||||
.fileinput-button input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
-ms-filter: 'alpha(opacity=0)';
|
||||
font-size: 200px;
|
||||
direction: ltr;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Fixes for IE < 8 */
|
||||
@media screen\9 {
|
||||
.fileinput-button input {
|
||||
filter: alpha(opacity=0);
|
||||
font-size: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* jQuery postMessage Transport Plugin 1.1.2
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* global define, require, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(require('jquery'));
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(window.jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
'use strict';
|
||||
|
||||
var counter = 0,
|
||||
names = [
|
||||
'accepts',
|
||||
'cache',
|
||||
'contents',
|
||||
'contentType',
|
||||
'crossDomain',
|
||||
'data',
|
||||
'dataType',
|
||||
'headers',
|
||||
'ifModified',
|
||||
'mimeType',
|
||||
'password',
|
||||
'processData',
|
||||
'timeout',
|
||||
'traditional',
|
||||
'type',
|
||||
'url',
|
||||
'username'
|
||||
],
|
||||
convert = function (p) {
|
||||
return p;
|
||||
};
|
||||
|
||||
$.ajaxSetup({
|
||||
converters: {
|
||||
'postmessage text': convert,
|
||||
'postmessage json': convert,
|
||||
'postmessage html': convert
|
||||
}
|
||||
});
|
||||
|
||||
$.ajaxTransport('postmessage', function (options) {
|
||||
if (options.postMessage && window.postMessage) {
|
||||
var iframe,
|
||||
loc = $('<a>').prop('href', options.postMessage)[0],
|
||||
target = loc.protocol + '//' + loc.host,
|
||||
xhrUpload = options.xhr().upload;
|
||||
return {
|
||||
send: function (_, completeCallback) {
|
||||
counter += 1;
|
||||
var message = {
|
||||
id: 'postmessage-transport-' + counter
|
||||
},
|
||||
eventName = 'message.' + message.id;
|
||||
iframe = $(
|
||||
'<iframe style="display:none;" src="' +
|
||||
options.postMessage + '" name="' +
|
||||
message.id + '"></iframe>'
|
||||
).bind('load', function () {
|
||||
$.each(names, function (i, name) {
|
||||
message[name] = options[name];
|
||||
});
|
||||
message.dataType = message.dataType.replace('postmessage ', '');
|
||||
$(window).bind(eventName, function (e) {
|
||||
e = e.originalEvent;
|
||||
var data = e.data,
|
||||
ev;
|
||||
if (e.origin === target && data.id === message.id) {
|
||||
if (data.type === 'progress') {
|
||||
ev = document.createEvent('Event');
|
||||
ev.initEvent(data.type, false, true);
|
||||
$.extend(ev, data);
|
||||
xhrUpload.dispatchEvent(ev);
|
||||
} else {
|
||||
completeCallback(
|
||||
data.status,
|
||||
data.statusText,
|
||||
{postmessage: data.result},
|
||||
data.headers
|
||||
);
|
||||
iframe.remove();
|
||||
$(window).unbind(eventName);
|
||||
}
|
||||
}
|
||||
});
|
||||
iframe[0].contentWindow.postMessage(
|
||||
message,
|
||||
target
|
||||
);
|
||||
}).appendTo(document.body);
|
||||
},
|
||||
abort: function () {
|
||||
if (iframe) {
|
||||
iframe.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* jQuery XDomainRequest Transport Plugin 1.1.4
|
||||
* 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
|
||||
*
|
||||
* Based on Julian Aubourg's ajaxHooks xdr.js:
|
||||
* https://github.com/jaubourg/ajaxHooks/
|
||||
*/
|
||||
|
||||
/* global define, require, window, XDomainRequest */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(require('jquery'));
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(window.jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
'use strict';
|
||||
if (window.XDomainRequest && !$.support.cors) {
|
||||
$.ajaxTransport(function (s) {
|
||||
if (s.crossDomain && s.async) {
|
||||
if (s.timeout) {
|
||||
s.xdrTimeout = s.timeout;
|
||||
delete s.timeout;
|
||||
}
|
||||
var xdr;
|
||||
return {
|
||||
send: function (headers, completeCallback) {
|
||||
var addParamChar = /\?/.test(s.url) ? '&' : '?';
|
||||
function callback(status, statusText, responses, responseHeaders) {
|
||||
xdr.onload = xdr.onerror = xdr.ontimeout = $.noop;
|
||||
xdr = null;
|
||||
completeCallback(status, statusText, responses, responseHeaders);
|
||||
}
|
||||
xdr = new XDomainRequest();
|
||||
// XDomainRequest only supports GET and POST:
|
||||
if (s.type === 'DELETE') {
|
||||
s.url = s.url + addParamChar + '_method=DELETE';
|
||||
s.type = 'POST';
|
||||
} else if (s.type === 'PUT') {
|
||||
s.url = s.url + addParamChar + '_method=PUT';
|
||||
s.type = 'POST';
|
||||
} else if (s.type === 'PATCH') {
|
||||
s.url = s.url + addParamChar + '_method=PATCH';
|
||||
s.type = 'POST';
|
||||
}
|
||||
xdr.open(s.type, s.url);
|
||||
xdr.onload = function () {
|
||||
callback(
|
||||
200,
|
||||
'OK',
|
||||
{text: xdr.responseText},
|
||||
'Content-Type: ' + xdr.contentType
|
||||
);
|
||||
};
|
||||
xdr.onerror = function () {
|
||||
callback(404, 'Not Found');
|
||||
};
|
||||
if (s.xdrTimeout) {
|
||||
xdr.ontimeout = function () {
|
||||
callback(0, 'timeout');
|
||||
};
|
||||
xdr.timeout = s.xdrTimeout;
|
||||
}
|
||||
xdr.send((s.hasContent && s.data) || null);
|
||||
},
|
||||
abort: function () {
|
||||
if (xdr) {
|
||||
xdr.onerror = $.noop();
|
||||
xdr.abort();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
* jQuery File Upload AngularJS Plugin 2.2.0
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* jshint nomen:false */
|
||||
/* global define, angular */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'jquery',
|
||||
'angular',
|
||||
'./jquery.fileupload-image',
|
||||
'./jquery.fileupload-audio',
|
||||
'./jquery.fileupload-video',
|
||||
'./jquery.fileupload-validate'
|
||||
], factory);
|
||||
} else {
|
||||
factory();
|
||||
}
|
||||
}(function () {
|
||||
'use strict';
|
||||
|
||||
angular.module('blueimp.fileupload', [])
|
||||
|
||||
// The fileUpload service provides configuration options
|
||||
// for the fileUpload directive and default handlers for
|
||||
// File Upload events:
|
||||
.provider('fileUpload', function () {
|
||||
var scopeEvalAsync = function (expression) {
|
||||
var scope = angular.element(this)
|
||||
.fileupload('option', 'scope');
|
||||
// Schedule a new $digest cycle if not already inside of one
|
||||
// and evaluate the given expression:
|
||||
scope.$evalAsync(expression);
|
||||
},
|
||||
addFileMethods = function (scope, data) {
|
||||
var files = data.files,
|
||||
file = files[0];
|
||||
angular.forEach(files, function (file, index) {
|
||||
file._index = index;
|
||||
file.$state = function () {
|
||||
return data.state();
|
||||
};
|
||||
file.$processing = function () {
|
||||
return data.processing();
|
||||
};
|
||||
file.$progress = function () {
|
||||
return data.progress();
|
||||
};
|
||||
file.$response = function () {
|
||||
return data.response();
|
||||
};
|
||||
});
|
||||
file.$submit = function () {
|
||||
if (!file.error) {
|
||||
return data.submit();
|
||||
}
|
||||
};
|
||||
file.$cancel = function () {
|
||||
return data.abort();
|
||||
};
|
||||
},
|
||||
$config;
|
||||
$config = this.defaults = {
|
||||
handleResponse: function (e, data) {
|
||||
var files = data.result && data.result.files;
|
||||
if (files) {
|
||||
data.scope.replace(data.files, files);
|
||||
} else if (data.errorThrown ||
|
||||
data.textStatus === 'error') {
|
||||
data.files[0].error = data.errorThrown ||
|
||||
data.textStatus;
|
||||
}
|
||||
},
|
||||
add: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var scope = data.scope,
|
||||
filesCopy = [];
|
||||
angular.forEach(data.files, function (file) {
|
||||
filesCopy.push(file);
|
||||
});
|
||||
scope.$apply(function () {
|
||||
addFileMethods(scope, data);
|
||||
var method = scope.option('prependFiles') ?
|
||||
'unshift' : 'push';
|
||||
Array.prototype[method].apply(scope.queue, data.files);
|
||||
});
|
||||
data.process(function () {
|
||||
return scope.process(data);
|
||||
}).always(function () {
|
||||
scope.$apply(function () {
|
||||
addFileMethods(scope, data);
|
||||
scope.replace(filesCopy, data.files);
|
||||
});
|
||||
}).then(function () {
|
||||
if ((scope.option('autoUpload') ||
|
||||
data.autoUpload) &&
|
||||
data.autoUpload !== false) {
|
||||
data.submit();
|
||||
}
|
||||
});
|
||||
},
|
||||
progress: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
data.scope.$apply();
|
||||
},
|
||||
done: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var that = this;
|
||||
data.scope.$apply(function () {
|
||||
data.handleResponse.call(that, e, data);
|
||||
});
|
||||
},
|
||||
fail: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var that = this,
|
||||
scope = data.scope;
|
||||
if (data.errorThrown === 'abort') {
|
||||
scope.clear(data.files);
|
||||
return;
|
||||
}
|
||||
scope.$apply(function () {
|
||||
data.handleResponse.call(that, e, data);
|
||||
});
|
||||
},
|
||||
stop: scopeEvalAsync,
|
||||
processstart: scopeEvalAsync,
|
||||
processstop: scopeEvalAsync,
|
||||
getNumberOfFiles: function () {
|
||||
var scope = this.scope;
|
||||
return scope.queue.length - scope.processing();
|
||||
},
|
||||
dataType: 'json',
|
||||
autoUpload: false
|
||||
};
|
||||
this.$get = [
|
||||
function () {
|
||||
return {
|
||||
defaults: $config
|
||||
};
|
||||
}
|
||||
];
|
||||
})
|
||||
|
||||
// Format byte numbers to readable presentations:
|
||||
.provider('formatFileSizeFilter', function () {
|
||||
var $config = {
|
||||
// Byte units following the IEC format
|
||||
// http://en.wikipedia.org/wiki/Kilobyte
|
||||
units: [
|
||||
{size: 1000000000, suffix: ' GB'},
|
||||
{size: 1000000, suffix: ' MB'},
|
||||
{size: 1000, suffix: ' KB'}
|
||||
]
|
||||
};
|
||||
this.defaults = $config;
|
||||
this.$get = function () {
|
||||
return function (bytes) {
|
||||
if (!angular.isNumber(bytes)) {
|
||||
return '';
|
||||
}
|
||||
var unit = true,
|
||||
i = 0,
|
||||
prefix,
|
||||
suffix;
|
||||
while (unit) {
|
||||
unit = $config.units[i];
|
||||
prefix = unit.prefix || '';
|
||||
suffix = unit.suffix || '';
|
||||
if (i === $config.units.length - 1 || bytes >= unit.size) {
|
||||
return prefix + (bytes / unit.size).toFixed(2) + suffix;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
// The FileUploadController initializes the fileupload widget and
|
||||
// provides scope methods to control the File Upload functionality:
|
||||
.controller('FileUploadController', [
|
||||
'$scope', '$element', '$attrs', '$window', 'fileUpload',
|
||||
function ($scope, $element, $attrs, $window, fileUpload) {
|
||||
var uploadMethods = {
|
||||
progress: function () {
|
||||
return $element.fileupload('progress');
|
||||
},
|
||||
active: function () {
|
||||
return $element.fileupload('active');
|
||||
},
|
||||
option: function (option, data) {
|
||||
if (arguments.length === 1) {
|
||||
return $element.fileupload('option', option);
|
||||
}
|
||||
$element.fileupload('option', option, data);
|
||||
},
|
||||
add: function (data) {
|
||||
return $element.fileupload('add', data);
|
||||
},
|
||||
send: function (data) {
|
||||
return $element.fileupload('send', data);
|
||||
},
|
||||
process: function (data) {
|
||||
return $element.fileupload('process', data);
|
||||
},
|
||||
processing: function (data) {
|
||||
return $element.fileupload('processing', data);
|
||||
}
|
||||
};
|
||||
$scope.disabled = !$window.jQuery.support.fileInput;
|
||||
$scope.queue = $scope.queue || [];
|
||||
$scope.clear = function (files) {
|
||||
var queue = this.queue,
|
||||
i = queue.length,
|
||||
file = files,
|
||||
length = 1;
|
||||
if (angular.isArray(files)) {
|
||||
file = files[0];
|
||||
length = files.length;
|
||||
}
|
||||
while (i) {
|
||||
i -= 1;
|
||||
if (queue[i] === file) {
|
||||
return queue.splice(i, length);
|
||||
}
|
||||
}
|
||||
};
|
||||
$scope.replace = function (oldFiles, newFiles) {
|
||||
var queue = this.queue,
|
||||
file = oldFiles[0],
|
||||
i,
|
||||
j;
|
||||
for (i = 0; i < queue.length; i += 1) {
|
||||
if (queue[i] === file) {
|
||||
for (j = 0; j < newFiles.length; j += 1) {
|
||||
queue[i + j] = newFiles[j];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
$scope.applyOnQueue = function (method) {
|
||||
var list = this.queue.slice(0),
|
||||
i,
|
||||
file;
|
||||
for (i = 0; i < list.length; i += 1) {
|
||||
file = list[i];
|
||||
if (file[method]) {
|
||||
file[method]();
|
||||
}
|
||||
}
|
||||
};
|
||||
$scope.submit = function () {
|
||||
this.applyOnQueue('$submit');
|
||||
};
|
||||
$scope.cancel = function () {
|
||||
this.applyOnQueue('$cancel');
|
||||
};
|
||||
// Add upload methods to the scope:
|
||||
angular.extend($scope, uploadMethods);
|
||||
// The fileupload widget will initialize with
|
||||
// the options provided via "data-"-parameters,
|
||||
// as well as those given via options object:
|
||||
$element.fileupload(angular.extend(
|
||||
{scope: $scope},
|
||||
fileUpload.defaults
|
||||
)).on('fileuploadadd', function (e, data) {
|
||||
data.scope = $scope;
|
||||
}).on('fileuploadfail', function (e, data) {
|
||||
if (data.errorThrown === 'abort') {
|
||||
return;
|
||||
}
|
||||
if (data.dataType &&
|
||||
data.dataType.indexOf('json') === data.dataType.length - 4) {
|
||||
try {
|
||||
data.result = angular.fromJson(data.jqXHR.responseText);
|
||||
} catch (ignore) {}
|
||||
}
|
||||
}).on([
|
||||
'fileuploadadd',
|
||||
'fileuploadsubmit',
|
||||
'fileuploadsend',
|
||||
'fileuploaddone',
|
||||
'fileuploadfail',
|
||||
'fileuploadalways',
|
||||
'fileuploadprogress',
|
||||
'fileuploadprogressall',
|
||||
'fileuploadstart',
|
||||
'fileuploadstop',
|
||||
'fileuploadchange',
|
||||
'fileuploadpaste',
|
||||
'fileuploaddrop',
|
||||
'fileuploaddragover',
|
||||
'fileuploadchunksend',
|
||||
'fileuploadchunkdone',
|
||||
'fileuploadchunkfail',
|
||||
'fileuploadchunkalways',
|
||||
'fileuploadprocessstart',
|
||||
'fileuploadprocess',
|
||||
'fileuploadprocessdone',
|
||||
'fileuploadprocessfail',
|
||||
'fileuploadprocessalways',
|
||||
'fileuploadprocessstop'
|
||||
].join(' '), function (e, data) {
|
||||
if ($scope.$emit(e.type, data).defaultPrevented) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}).on('remove', function () {
|
||||
// Remove upload methods from the scope,
|
||||
// when the widget is removed:
|
||||
var method;
|
||||
for (method in uploadMethods) {
|
||||
if (uploadMethods.hasOwnProperty(method)) {
|
||||
delete $scope[method];
|
||||
}
|
||||
}
|
||||
});
|
||||
// Observe option changes:
|
||||
$scope.$watch(
|
||||
$attrs.fileUpload,
|
||||
function (newOptions) {
|
||||
if (newOptions) {
|
||||
$element.fileupload('option', newOptions);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
])
|
||||
|
||||
// Provide File Upload progress feedback:
|
||||
.controller('FileUploadProgressController', [
|
||||
'$scope', '$attrs', '$parse',
|
||||
function ($scope, $attrs, $parse) {
|
||||
var fn = $parse($attrs.fileUploadProgress),
|
||||
update = function () {
|
||||
var progress = fn($scope);
|
||||
if (!progress || !progress.total) {
|
||||
return;
|
||||
}
|
||||
$scope.num = Math.floor(
|
||||
progress.loaded / progress.total * 100
|
||||
);
|
||||
};
|
||||
update();
|
||||
$scope.$watch(
|
||||
$attrs.fileUploadProgress + '.loaded',
|
||||
function (newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
])
|
||||
|
||||
// Display File Upload previews:
|
||||
.controller('FileUploadPreviewController', [
|
||||
'$scope', '$element', '$attrs',
|
||||
function ($scope, $element, $attrs) {
|
||||
$scope.$watch(
|
||||
$attrs.fileUploadPreview + '.preview',
|
||||
function (preview) {
|
||||
$element.empty();
|
||||
if (preview) {
|
||||
$element.append(preview);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
])
|
||||
|
||||
.directive('fileUpload', function () {
|
||||
return {
|
||||
controller: 'FileUploadController',
|
||||
scope: true
|
||||
};
|
||||
})
|
||||
|
||||
.directive('fileUploadProgress', function () {
|
||||
return {
|
||||
controller: 'FileUploadProgressController',
|
||||
scope: true
|
||||
};
|
||||
})
|
||||
|
||||
.directive('fileUploadPreview', function () {
|
||||
return {
|
||||
controller: 'FileUploadPreviewController'
|
||||
};
|
||||
})
|
||||
|
||||
// Enhance the HTML5 download attribute to
|
||||
// allow drag&drop of files to the desktop:
|
||||
.directive('download', function () {
|
||||
return function (scope, elm) {
|
||||
elm.on('dragstart', function (e) {
|
||||
try {
|
||||
e.originalEvent.dataTransfer.setData(
|
||||
'DownloadURL',
|
||||
[
|
||||
'application/octet-stream',
|
||||
elm.prop('download'),
|
||||
elm.prop('href')
|
||||
].join(':')
|
||||
);
|
||||
} catch (ignore) {}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* jQuery File Upload Audio Preview Plugin 1.0.4
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* jshint nomen:false */
|
||||
/* global define, require, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'jquery',
|
||||
'load-image',
|
||||
'./jquery.fileupload-process'
|
||||
], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(
|
||||
require('jquery'),
|
||||
require('load-image')
|
||||
);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.jQuery,
|
||||
window.loadImage
|
||||
);
|
||||
}
|
||||
}(function ($, loadImage) {
|
||||
'use strict';
|
||||
|
||||
// Prepend to the default processQueue:
|
||||
$.blueimp.fileupload.prototype.options.processQueue.unshift(
|
||||
{
|
||||
action: 'loadAudio',
|
||||
// Use the action as prefix for the "@" options:
|
||||
prefix: true,
|
||||
fileTypes: '@',
|
||||
maxFileSize: '@',
|
||||
disabled: '@disableAudioPreview'
|
||||
},
|
||||
{
|
||||
action: 'setAudio',
|
||||
name: '@audioPreviewName',
|
||||
disabled: '@disableAudioPreview'
|
||||
}
|
||||
);
|
||||
|
||||
// The File Upload Audio Preview plugin extends the fileupload widget
|
||||
// with audio preview functionality:
|
||||
$.widget('blueimp.fileupload', $.blueimp.fileupload, {
|
||||
|
||||
options: {
|
||||
// The regular expression for the types of audio files to load,
|
||||
// matched against the file type:
|
||||
loadAudioFileTypes: /^audio\/.*$/
|
||||
},
|
||||
|
||||
_audioElement: document.createElement('audio'),
|
||||
|
||||
processActions: {
|
||||
|
||||
// Loads the audio file given via data.files and data.index
|
||||
// as audio element if the browser supports playing it.
|
||||
// Accepts the options fileTypes (regular expression)
|
||||
// and maxFileSize (integer) to limit the files to load:
|
||||
loadAudio: function (data, options) {
|
||||
if (options.disabled) {
|
||||
return data;
|
||||
}
|
||||
var file = data.files[data.index],
|
||||
url,
|
||||
audio;
|
||||
if (this._audioElement.canPlayType &&
|
||||
this._audioElement.canPlayType(file.type) &&
|
||||
($.type(options.maxFileSize) !== 'number' ||
|
||||
file.size <= options.maxFileSize) &&
|
||||
(!options.fileTypes ||
|
||||
options.fileTypes.test(file.type))) {
|
||||
url = loadImage.createObjectURL(file);
|
||||
if (url) {
|
||||
audio = this._audioElement.cloneNode(false);
|
||||
audio.src = url;
|
||||
audio.controls = true;
|
||||
data.audio = audio;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
// Sets the audio element as a property of the file object:
|
||||
setAudio: function (data, options) {
|
||||
if (data.audio && !options.disabled) {
|
||||
data.files[data.index][options.name || 'preview'] = data.audio;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* jQuery File Upload Image Preview & Resize Plugin 1.7.3
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* jshint nomen:false */
|
||||
/* global define, require, window, Blob */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'jquery',
|
||||
'load-image',
|
||||
'load-image-meta',
|
||||
'load-image-exif',
|
||||
'load-image-ios',
|
||||
'canvas-to-blob',
|
||||
'./jquery.fileupload-process'
|
||||
], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(
|
||||
require('jquery'),
|
||||
require('load-image')
|
||||
);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.jQuery,
|
||||
window.loadImage
|
||||
);
|
||||
}
|
||||
}(function ($, loadImage) {
|
||||
'use strict';
|
||||
|
||||
// Prepend to the default processQueue:
|
||||
$.blueimp.fileupload.prototype.options.processQueue.unshift(
|
||||
{
|
||||
action: 'loadImageMetaData',
|
||||
disableImageHead: '@',
|
||||
disableExif: '@',
|
||||
disableExifThumbnail: '@',
|
||||
disableExifSub: '@',
|
||||
disableExifGps: '@',
|
||||
disabled: '@disableImageMetaDataLoad'
|
||||
},
|
||||
{
|
||||
action: 'loadImage',
|
||||
// Use the action as prefix for the "@" options:
|
||||
prefix: true,
|
||||
fileTypes: '@',
|
||||
maxFileSize: '@',
|
||||
noRevoke: '@',
|
||||
disabled: '@disableImageLoad'
|
||||
},
|
||||
{
|
||||
action: 'resizeImage',
|
||||
// Use "image" as prefix for the "@" options:
|
||||
prefix: 'image',
|
||||
maxWidth: '@',
|
||||
maxHeight: '@',
|
||||
minWidth: '@',
|
||||
minHeight: '@',
|
||||
crop: '@',
|
||||
orientation: '@',
|
||||
forceResize: '@',
|
||||
disabled: '@disableImageResize'
|
||||
},
|
||||
{
|
||||
action: 'saveImage',
|
||||
quality: '@imageQuality',
|
||||
type: '@imageType',
|
||||
disabled: '@disableImageResize'
|
||||
},
|
||||
{
|
||||
action: 'saveImageMetaData',
|
||||
disabled: '@disableImageMetaDataSave'
|
||||
},
|
||||
{
|
||||
action: 'resizeImage',
|
||||
// Use "preview" as prefix for the "@" options:
|
||||
prefix: 'preview',
|
||||
maxWidth: '@',
|
||||
maxHeight: '@',
|
||||
minWidth: '@',
|
||||
minHeight: '@',
|
||||
crop: '@',
|
||||
orientation: '@',
|
||||
thumbnail: '@',
|
||||
canvas: '@',
|
||||
disabled: '@disableImagePreview'
|
||||
},
|
||||
{
|
||||
action: 'setImage',
|
||||
name: '@imagePreviewName',
|
||||
disabled: '@disableImagePreview'
|
||||
},
|
||||
{
|
||||
action: 'deleteImageReferences',
|
||||
disabled: '@disableImageReferencesDeletion'
|
||||
}
|
||||
);
|
||||
|
||||
// The File Upload Resize plugin extends the fileupload widget
|
||||
// with image resize functionality:
|
||||
$.widget('blueimp.fileupload', $.blueimp.fileupload, {
|
||||
|
||||
options: {
|
||||
// The regular expression for the types of images to load:
|
||||
// matched against the file type:
|
||||
loadImageFileTypes: /^image\/(gif|jpeg|png|svg\+xml)$/,
|
||||
// The maximum file size of images to load:
|
||||
loadImageMaxFileSize: 10000000, // 10MB
|
||||
// The maximum width of resized images:
|
||||
imageMaxWidth: 1920,
|
||||
// The maximum height of resized images:
|
||||
imageMaxHeight: 1080,
|
||||
// Defines the image orientation (1-8) or takes the orientation
|
||||
// value from Exif data if set to true:
|
||||
imageOrientation: false,
|
||||
// Define if resized images should be cropped or only scaled:
|
||||
imageCrop: false,
|
||||
// Disable the resize image functionality by default:
|
||||
disableImageResize: true,
|
||||
// The maximum width of the preview images:
|
||||
previewMaxWidth: 80,
|
||||
// The maximum height of the preview images:
|
||||
previewMaxHeight: 80,
|
||||
// Defines the preview orientation (1-8) or takes the orientation
|
||||
// value from Exif data if set to true:
|
||||
previewOrientation: true,
|
||||
// Create the preview using the Exif data thumbnail:
|
||||
previewThumbnail: true,
|
||||
// Define if preview images should be cropped or only scaled:
|
||||
previewCrop: false,
|
||||
// Define if preview images should be resized as canvas elements:
|
||||
previewCanvas: true
|
||||
},
|
||||
|
||||
processActions: {
|
||||
|
||||
// Loads the image given via data.files and data.index
|
||||
// as img element, if the browser supports the File API.
|
||||
// Accepts the options fileTypes (regular expression)
|
||||
// and maxFileSize (integer) to limit the files to load:
|
||||
loadImage: function (data, options) {
|
||||
if (options.disabled) {
|
||||
return data;
|
||||
}
|
||||
var that = this,
|
||||
file = data.files[data.index],
|
||||
dfd = $.Deferred();
|
||||
if (($.type(options.maxFileSize) === 'number' &&
|
||||
file.size > options.maxFileSize) ||
|
||||
(options.fileTypes &&
|
||||
!options.fileTypes.test(file.type)) ||
|
||||
!loadImage(
|
||||
file,
|
||||
function (img) {
|
||||
if (img.src) {
|
||||
data.img = img;
|
||||
}
|
||||
dfd.resolveWith(that, [data]);
|
||||
},
|
||||
options
|
||||
)) {
|
||||
return data;
|
||||
}
|
||||
return dfd.promise();
|
||||
},
|
||||
|
||||
// Resizes the image given as data.canvas or data.img
|
||||
// and updates data.canvas or data.img with the resized image.
|
||||
// Also stores the resized image as preview property.
|
||||
// Accepts the options maxWidth, maxHeight, minWidth,
|
||||
// minHeight, canvas and crop:
|
||||
resizeImage: function (data, options) {
|
||||
if (options.disabled || !(data.canvas || data.img)) {
|
||||
return data;
|
||||
}
|
||||
options = $.extend({canvas: true}, options);
|
||||
var that = this,
|
||||
dfd = $.Deferred(),
|
||||
img = (options.canvas && data.canvas) || data.img,
|
||||
resolve = function (newImg) {
|
||||
if (newImg && (newImg.width !== img.width ||
|
||||
newImg.height !== img.height ||
|
||||
options.forceResize)) {
|
||||
data[newImg.getContext ? 'canvas' : 'img'] = newImg;
|
||||
}
|
||||
data.preview = newImg;
|
||||
dfd.resolveWith(that, [data]);
|
||||
},
|
||||
thumbnail;
|
||||
if (data.exif) {
|
||||
if (options.orientation === true) {
|
||||
options.orientation = data.exif.get('Orientation');
|
||||
}
|
||||
if (options.thumbnail) {
|
||||
thumbnail = data.exif.get('Thumbnail');
|
||||
if (thumbnail) {
|
||||
loadImage(thumbnail, resolve, options);
|
||||
return dfd.promise();
|
||||
}
|
||||
}
|
||||
// Prevent orienting the same image twice:
|
||||
if (data.orientation) {
|
||||
delete options.orientation;
|
||||
} else {
|
||||
data.orientation = options.orientation;
|
||||
}
|
||||
}
|
||||
if (img) {
|
||||
resolve(loadImage.scale(img, options));
|
||||
return dfd.promise();
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
// Saves the processed image given as data.canvas
|
||||
// inplace at data.index of data.files:
|
||||
saveImage: function (data, options) {
|
||||
if (!data.canvas || options.disabled) {
|
||||
return data;
|
||||
}
|
||||
var that = this,
|
||||
file = data.files[data.index],
|
||||
dfd = $.Deferred();
|
||||
if (data.canvas.toBlob) {
|
||||
data.canvas.toBlob(
|
||||
function (blob) {
|
||||
if (!blob.name) {
|
||||
if (file.type === blob.type) {
|
||||
blob.name = file.name;
|
||||
} else if (file.name) {
|
||||
blob.name = file.name.replace(
|
||||
/\.\w+$/,
|
||||
'.' + blob.type.substr(6)
|
||||
);
|
||||
}
|
||||
}
|
||||
// Don't restore invalid meta data:
|
||||
if (file.type !== blob.type) {
|
||||
delete data.imageHead;
|
||||
}
|
||||
// Store the created blob at the position
|
||||
// of the original file in the files list:
|
||||
data.files[data.index] = blob;
|
||||
dfd.resolveWith(that, [data]);
|
||||
},
|
||||
options.type || file.type,
|
||||
options.quality
|
||||
);
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
return dfd.promise();
|
||||
},
|
||||
|
||||
loadImageMetaData: function (data, options) {
|
||||
if (options.disabled) {
|
||||
return data;
|
||||
}
|
||||
var that = this,
|
||||
dfd = $.Deferred();
|
||||
loadImage.parseMetaData(data.files[data.index], function (result) {
|
||||
$.extend(data, result);
|
||||
dfd.resolveWith(that, [data]);
|
||||
}, options);
|
||||
return dfd.promise();
|
||||
},
|
||||
|
||||
saveImageMetaData: function (data, options) {
|
||||
if (!(data.imageHead && data.canvas &&
|
||||
data.canvas.toBlob && !options.disabled)) {
|
||||
return data;
|
||||
}
|
||||
var file = data.files[data.index],
|
||||
blob = new Blob([
|
||||
data.imageHead,
|
||||
// Resized images always have a head size of 20 bytes,
|
||||
// including the JPEG marker and a minimal JFIF header:
|
||||
this._blobSlice.call(file, 20)
|
||||
], {type: file.type});
|
||||
blob.name = file.name;
|
||||
data.files[data.index] = blob;
|
||||
return data;
|
||||
},
|
||||
|
||||
// Sets the resized version of the image as a property of the
|
||||
// file object, must be called after "saveImage":
|
||||
setImage: function (data, options) {
|
||||
if (data.preview && !options.disabled) {
|
||||
data.files[data.index][options.name || 'preview'] = data.preview;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
deleteImageReferences: function (data, options) {
|
||||
if (!options.disabled) {
|
||||
delete data.img;
|
||||
delete data.canvas;
|
||||
delete data.preview;
|
||||
delete data.imageHead;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* jQuery File Upload jQuery UI Plugin 8.7.2
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* jshint nomen:false */
|
||||
/* global define, require, window */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['jquery', './jquery.fileupload-ui'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(require('jquery'));
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(window.jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
'use strict';
|
||||
|
||||
$.widget('blueimp.fileupload', $.blueimp.fileupload, {
|
||||
|
||||
options: {
|
||||
processdone: function (e, data) {
|
||||
data.context.find('.start').button('enable');
|
||||
},
|
||||
progress: function (e, data) {
|
||||
if (data.context) {
|
||||
data.context.find('.progress').progressbar(
|
||||
'option',
|
||||
'value',
|
||||
parseInt(data.loaded / data.total * 100, 10)
|
||||
);
|
||||
}
|
||||
},
|
||||
progressall: function (e, data) {
|
||||
var $this = $(this);
|
||||
$this.find('.fileupload-progress')
|
||||
.find('.progress').progressbar(
|
||||
'option',
|
||||
'value',
|
||||
parseInt(data.loaded / data.total * 100, 10)
|
||||
).end()
|
||||
.find('.progress-extended').each(function () {
|
||||
$(this).html(
|
||||
($this.data('blueimp-fileupload') ||
|
||||
$this.data('fileupload'))
|
||||
._renderExtendedProgress(data)
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_renderUpload: function (func, files) {
|
||||
var node = this._super(func, files),
|
||||
showIconText = $(window).width() > 480;
|
||||
node.find('.progress').empty().progressbar();
|
||||
node.find('.start').button({
|
||||
icons: {primary: 'ui-icon-circle-arrow-e'},
|
||||
text: showIconText
|
||||
});
|
||||
node.find('.cancel').button({
|
||||
icons: {primary: 'ui-icon-cancel'},
|
||||
text: showIconText
|
||||
});
|
||||
if (node.hasClass('fade')) {
|
||||
node.hide();
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
_renderDownload: function (func, files) {
|
||||
var node = this._super(func, files),
|
||||
showIconText = $(window).width() > 480;
|
||||
node.find('.delete').button({
|
||||
icons: {primary: 'ui-icon-trash'},
|
||||
text: showIconText
|
||||
});
|
||||
if (node.hasClass('fade')) {
|
||||
node.hide();
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
_startHandler: function (e) {
|
||||
$(e.currentTarget).button('disable');
|
||||
this._super(e);
|
||||
},
|
||||
|
||||
_transition: function (node) {
|
||||
var deferred = $.Deferred();
|
||||
if (node.hasClass('fade')) {
|
||||
node.fadeToggle(
|
||||
this.options.transitionDuration,
|
||||
this.options.transitionEasing,
|
||||
function () {
|
||||
deferred.resolveWith(node);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
deferred.resolveWith(node);
|
||||
}
|
||||
return deferred;
|
||||
},
|
||||
|
||||
_create: function () {
|
||||
this._super();
|
||||
this.element
|
||||
.find('.fileupload-buttonbar')
|
||||
.find('.fileinput-button').each(function () {
|
||||
var input = $(this).find('input:file').detach();
|
||||
$(this)
|
||||
.button({icons: {primary: 'ui-icon-plusthick'}})
|
||||
.append(input);
|
||||
})
|
||||
.end().find('.start')
|
||||
.button({icons: {primary: 'ui-icon-circle-arrow-e'}})
|
||||
.end().find('.cancel')
|
||||
.button({icons: {primary: 'ui-icon-cancel'}})
|
||||
.end().find('.delete')
|
||||
.button({icons: {primary: 'ui-icon-trash'}})
|
||||
.end().find('.progress').progressbar();
|
||||
},
|
||||
|
||||
_destroy: function () {
|
||||
this.element
|
||||
.find('.fileupload-buttonbar')
|
||||
.find('.fileinput-button').each(function () {
|
||||
var input = $(this).find('input:file').detach();
|
||||
$(this)
|
||||
.button('destroy')
|
||||
.append(input);
|
||||
})
|
||||
.end().find('.start')
|
||||
.button('destroy')
|
||||
.end().find('.cancel')
|
||||
.button('destroy')
|
||||
.end().find('.delete')
|
||||
.button('destroy')
|
||||
.end().find('.progress').progressbar('destroy');
|
||||
this._super();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* jQuery File Upload Processing Plugin 1.3.1
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2012, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* jshint nomen:false */
|
||||
/* global define, require, window */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'jquery',
|
||||
'./jquery.fileupload'
|
||||
], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(require('jquery'));
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.jQuery
|
||||
);
|
||||
}
|
||||
}(function ($) {
|
||||
'use strict';
|
||||
|
||||
var originalAdd = $.blueimp.fileupload.prototype.options.add;
|
||||
|
||||
// The File Upload Processing plugin extends the fileupload widget
|
||||
// with file processing functionality:
|
||||
$.widget('blueimp.fileupload', $.blueimp.fileupload, {
|
||||
|
||||
options: {
|
||||
// The list of processing actions:
|
||||
processQueue: [
|
||||
/*
|
||||
{
|
||||
action: 'log',
|
||||
type: 'debug'
|
||||
}
|
||||
*/
|
||||
],
|
||||
add: function (e, data) {
|
||||
var $this = $(this);
|
||||
data.process(function () {
|
||||
return $this.fileupload('process', data);
|
||||
});
|
||||
originalAdd.call(this, e, data);
|
||||
}
|
||||
},
|
||||
|
||||
processActions: {
|
||||
/*
|
||||
log: function (data, options) {
|
||||
console[options.type](
|
||||
'Processing "' + data.files[data.index].name + '"'
|
||||
);
|
||||
}
|
||||
*/
|
||||
},
|
||||
|
||||
_processFile: function (data, originalData) {
|
||||
var that = this,
|
||||
dfd = $.Deferred().resolveWith(that, [data]),
|
||||
chain = dfd.promise();
|
||||
this._trigger('process', null, data);
|
||||
$.each(data.processQueue, function (i, settings) {
|
||||
var func = function (data) {
|
||||
if (originalData.errorThrown) {
|
||||
return $.Deferred()
|
||||
.rejectWith(that, [originalData]).promise();
|
||||
}
|
||||
return that.processActions[settings.action].call(
|
||||
that,
|
||||
data,
|
||||
settings
|
||||
);
|
||||
};
|
||||
chain = chain.pipe(func, settings.always && func);
|
||||
});
|
||||
chain
|
||||
.done(function () {
|
||||
that._trigger('processdone', null, data);
|
||||
that._trigger('processalways', null, data);
|
||||
})
|
||||
.fail(function () {
|
||||
that._trigger('processfail', null, data);
|
||||
that._trigger('processalways', null, data);
|
||||
});
|
||||
return chain;
|
||||
},
|
||||
|
||||
// Replaces the settings of each processQueue item that
|
||||
// are strings starting with an "@", using the remaining
|
||||
// substring as key for the option map,
|
||||
// e.g. "@autoUpload" is replaced with options.autoUpload:
|
||||
_transformProcessQueue: function (options) {
|
||||
var processQueue = [];
|
||||
$.each(options.processQueue, function () {
|
||||
var settings = {},
|
||||
action = this.action,
|
||||
prefix = this.prefix === true ? action : this.prefix;
|
||||
$.each(this, function (key, value) {
|
||||
if ($.type(value) === 'string' &&
|
||||
value.charAt(0) === '@') {
|
||||
settings[key] = options[
|
||||
value.slice(1) || (prefix ? prefix +
|
||||
key.charAt(0).toUpperCase() + key.slice(1) : key)
|
||||
];
|
||||
} else {
|
||||
settings[key] = value;
|
||||
}
|
||||
|
||||
});
|
||||
processQueue.push(settings);
|
||||
});
|
||||
options.processQueue = processQueue;
|
||||
},
|
||||
|
||||
// Returns the number of files currently in the processsing queue:
|
||||
processing: function () {
|
||||
return this._processing;
|
||||
},
|
||||
|
||||
// Processes the files given as files property of the data parameter,
|
||||
// returns a Promise object that allows to bind callbacks:
|
||||
process: function (data) {
|
||||
var that = this,
|
||||
options = $.extend({}, this.options, data);
|
||||
if (options.processQueue && options.processQueue.length) {
|
||||
this._transformProcessQueue(options);
|
||||
if (this._processing === 0) {
|
||||
this._trigger('processstart');
|
||||
}
|
||||
$.each(data.files, function (index) {
|
||||
var opts = index ? $.extend({}, options) : options,
|
||||
func = function () {
|
||||
if (data.errorThrown) {
|
||||
return $.Deferred()
|
||||
.rejectWith(that, [data]).promise();
|
||||
}
|
||||
return that._processFile(opts, data);
|
||||
};
|
||||
opts.index = index;
|
||||
that._processing += 1;
|
||||
that._processingQueue = that._processingQueue.pipe(func, func)
|
||||
.always(function () {
|
||||
that._processing -= 1;
|
||||
if (that._processing === 0) {
|
||||
that._trigger('processstop');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
return this._processingQueue;
|
||||
},
|
||||
|
||||
_create: function () {
|
||||
this._super();
|
||||
this._processing = 0;
|
||||
this._processingQueue = $.Deferred().resolveWith(this)
|
||||
.promise();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,710 @@
|
||||
/*
|
||||
* jQuery File Upload User Interface Plugin 9.6.1
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* jshint nomen:false */
|
||||
/* global define, require, window */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'jquery',
|
||||
'tmpl',
|
||||
'./jquery.fileupload-image',
|
||||
'./jquery.fileupload-audio',
|
||||
'./jquery.fileupload-video',
|
||||
'./jquery.fileupload-validate'
|
||||
], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(
|
||||
require('jquery'),
|
||||
require('tmpl')
|
||||
);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.jQuery,
|
||||
window.tmpl
|
||||
);
|
||||
}
|
||||
}(function ($, tmpl) {
|
||||
'use strict';
|
||||
|
||||
$.blueimp.fileupload.prototype._specialOptions.push(
|
||||
'filesContainer',
|
||||
'uploadTemplateId',
|
||||
'downloadTemplateId'
|
||||
);
|
||||
|
||||
// The UI version extends the file upload widget
|
||||
// and adds complete user interface interaction:
|
||||
$.widget('blueimp.fileupload', $.blueimp.fileupload, {
|
||||
|
||||
options: {
|
||||
// By default, files added to the widget are uploaded as soon
|
||||
// as the user clicks on the start buttons. To enable automatic
|
||||
// uploads, set the following option to true:
|
||||
autoUpload: false,
|
||||
// The ID of the upload template:
|
||||
uploadTemplateId: 'template-upload',
|
||||
// The ID of the download template:
|
||||
downloadTemplateId: 'template-download',
|
||||
// The container for the list of files. If undefined, it is set to
|
||||
// an element with class "files" inside of the widget element:
|
||||
filesContainer: undefined,
|
||||
// By default, files are appended to the files container.
|
||||
// Set the following option to true, to prepend files instead:
|
||||
prependFiles: false,
|
||||
// The expected data type of the upload response, sets the dataType
|
||||
// option of the $.ajax upload requests:
|
||||
dataType: 'json',
|
||||
|
||||
// Error and info messages:
|
||||
messages: {
|
||||
unknownError: 'Unknown error'
|
||||
},
|
||||
|
||||
// Function returning the current number of files,
|
||||
// used by the maxNumberOfFiles validation:
|
||||
getNumberOfFiles: function () {
|
||||
return this.filesContainer.children()
|
||||
.not('.processing').length;
|
||||
},
|
||||
|
||||
// Callback to retrieve the list of files from the server response:
|
||||
getFilesFromResponse: function (data) {
|
||||
if (data.result && $.isArray(data.result.files)) {
|
||||
return data.result.files;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
// The add callback is invoked as soon as files are added to the fileupload
|
||||
// widget (via file input selection, drag & drop or add API call).
|
||||
// See the basic file upload widget for more information:
|
||||
add: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var $this = $(this),
|
||||
that = $this.data('blueimp-fileupload') ||
|
||||
$this.data('fileupload'),
|
||||
options = that.options;
|
||||
data.context = that._renderUpload(data.files)
|
||||
.data('data', data)
|
||||
.addClass('processing');
|
||||
options.filesContainer[
|
||||
options.prependFiles ? 'prepend' : 'append'
|
||||
](data.context);
|
||||
that._forceReflow(data.context);
|
||||
that._transition(data.context);
|
||||
data.process(function () {
|
||||
return $this.fileupload('process', data);
|
||||
}).always(function () {
|
||||
data.context.each(function (index) {
|
||||
$(this).find('.size').text(
|
||||
that._formatFileSize(data.files[index].size)
|
||||
);
|
||||
}).removeClass('processing');
|
||||
that._renderPreviews(data);
|
||||
}).done(function () {
|
||||
data.context.find('.start').prop('disabled', false);
|
||||
if ((that._trigger('added', e, data) !== false) &&
|
||||
(options.autoUpload || data.autoUpload) &&
|
||||
data.autoUpload !== false) {
|
||||
data.submit();
|
||||
}
|
||||
}).fail(function () {
|
||||
if (data.files.error) {
|
||||
data.context.each(function (index) {
|
||||
var error = data.files[index].error;
|
||||
if (error) {
|
||||
$(this).find('.error').text(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// Callback for the start of each file upload request:
|
||||
send: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var that = $(this).data('blueimp-fileupload') ||
|
||||
$(this).data('fileupload');
|
||||
if (data.context && data.dataType &&
|
||||
data.dataType.substr(0, 6) === 'iframe') {
|
||||
// Iframe Transport does not support progress events.
|
||||
// In lack of an indeterminate progress bar, we set
|
||||
// the progress to 100%, showing the full animated bar:
|
||||
data.context
|
||||
.find('.progress').addClass(
|
||||
!$.support.transition && 'progress-animated'
|
||||
)
|
||||
.attr('aria-valuenow', 100)
|
||||
.children().first().css(
|
||||
'width',
|
||||
'100%'
|
||||
);
|
||||
}
|
||||
return that._trigger('sent', e, data);
|
||||
},
|
||||
// Callback for successful uploads:
|
||||
done: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var that = $(this).data('blueimp-fileupload') ||
|
||||
$(this).data('fileupload'),
|
||||
getFilesFromResponse = data.getFilesFromResponse ||
|
||||
that.options.getFilesFromResponse,
|
||||
files = getFilesFromResponse(data),
|
||||
template,
|
||||
deferred;
|
||||
if (data.context) {
|
||||
data.context.each(function (index) {
|
||||
var file = files[index] ||
|
||||
{error: 'Empty file upload result'};
|
||||
deferred = that._addFinishedDeferreds();
|
||||
that._transition($(this)).done(
|
||||
function () {
|
||||
var node = $(this);
|
||||
template = that._renderDownload([file])
|
||||
.replaceAll(node);
|
||||
that._forceReflow(template);
|
||||
that._transition(template).done(
|
||||
function () {
|
||||
data.context = $(this);
|
||||
that._trigger('completed', e, data);
|
||||
that._trigger('finished', e, data);
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
template = that._renderDownload(files)[
|
||||
that.options.prependFiles ? 'prependTo' : 'appendTo'
|
||||
](that.options.filesContainer);
|
||||
that._forceReflow(template);
|
||||
deferred = that._addFinishedDeferreds();
|
||||
that._transition(template).done(
|
||||
function () {
|
||||
data.context = $(this);
|
||||
that._trigger('completed', e, data);
|
||||
that._trigger('finished', e, data);
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
// Callback for failed (abort or error) uploads:
|
||||
fail: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var that = $(this).data('blueimp-fileupload') ||
|
||||
$(this).data('fileupload'),
|
||||
template,
|
||||
deferred;
|
||||
if (data.context) {
|
||||
data.context.each(function (index) {
|
||||
if (data.errorThrown !== 'abort') {
|
||||
var file = data.files[index];
|
||||
file.error = file.error || data.errorThrown ||
|
||||
data.i18n('unknownError');
|
||||
deferred = that._addFinishedDeferreds();
|
||||
that._transition($(this)).done(
|
||||
function () {
|
||||
var node = $(this);
|
||||
template = that._renderDownload([file])
|
||||
.replaceAll(node);
|
||||
that._forceReflow(template);
|
||||
that._transition(template).done(
|
||||
function () {
|
||||
data.context = $(this);
|
||||
that._trigger('failed', e, data);
|
||||
that._trigger('finished', e, data);
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
deferred = that._addFinishedDeferreds();
|
||||
that._transition($(this)).done(
|
||||
function () {
|
||||
$(this).remove();
|
||||
that._trigger('failed', e, data);
|
||||
that._trigger('finished', e, data);
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
} else if (data.errorThrown !== 'abort') {
|
||||
data.context = that._renderUpload(data.files)[
|
||||
that.options.prependFiles ? 'prependTo' : 'appendTo'
|
||||
](that.options.filesContainer)
|
||||
.data('data', data);
|
||||
that._forceReflow(data.context);
|
||||
deferred = that._addFinishedDeferreds();
|
||||
that._transition(data.context).done(
|
||||
function () {
|
||||
data.context = $(this);
|
||||
that._trigger('failed', e, data);
|
||||
that._trigger('finished', e, data);
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
that._trigger('failed', e, data);
|
||||
that._trigger('finished', e, data);
|
||||
that._addFinishedDeferreds().resolve();
|
||||
}
|
||||
},
|
||||
// Callback for upload progress events:
|
||||
progress: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var progress = Math.floor(data.loaded / data.total * 100);
|
||||
if (data.context) {
|
||||
data.context.each(function () {
|
||||
$(this).find('.progress')
|
||||
.attr('aria-valuenow', progress)
|
||||
.children().first().css(
|
||||
'width',
|
||||
progress + '%'
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
// Callback for global upload progress events:
|
||||
progressall: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var $this = $(this),
|
||||
progress = Math.floor(data.loaded / data.total * 100),
|
||||
globalProgressNode = $this.find('.fileupload-progress'),
|
||||
extendedProgressNode = globalProgressNode
|
||||
.find('.progress-extended');
|
||||
if (extendedProgressNode.length) {
|
||||
extendedProgressNode.html(
|
||||
($this.data('blueimp-fileupload') || $this.data('fileupload'))
|
||||
._renderExtendedProgress(data)
|
||||
);
|
||||
}
|
||||
globalProgressNode
|
||||
.find('.progress')
|
||||
.attr('aria-valuenow', progress)
|
||||
.children().first().css(
|
||||
'width',
|
||||
progress + '%'
|
||||
);
|
||||
},
|
||||
// Callback for uploads start, equivalent to the global ajaxStart event:
|
||||
start: function (e) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var that = $(this).data('blueimp-fileupload') ||
|
||||
$(this).data('fileupload');
|
||||
that._resetFinishedDeferreds();
|
||||
that._transition($(this).find('.fileupload-progress')).done(
|
||||
function () {
|
||||
that._trigger('started', e);
|
||||
}
|
||||
);
|
||||
},
|
||||
// Callback for uploads stop, equivalent to the global ajaxStop event:
|
||||
stop: function (e) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var that = $(this).data('blueimp-fileupload') ||
|
||||
$(this).data('fileupload'),
|
||||
deferred = that._addFinishedDeferreds();
|
||||
$.when.apply($, that._getFinishedDeferreds())
|
||||
.done(function () {
|
||||
that._trigger('stopped', e);
|
||||
});
|
||||
that._transition($(this).find('.fileupload-progress')).done(
|
||||
function () {
|
||||
$(this).find('.progress')
|
||||
.attr('aria-valuenow', '0')
|
||||
.children().first().css('width', '0%');
|
||||
$(this).find('.progress-extended').html(' ');
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
},
|
||||
processstart: function (e) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
$(this).addClass('fileupload-processing');
|
||||
},
|
||||
processstop: function (e) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
$(this).removeClass('fileupload-processing');
|
||||
},
|
||||
// Callback for file deletion:
|
||||
destroy: function (e, data) {
|
||||
if (e.isDefaultPrevented()) {
|
||||
return false;
|
||||
}
|
||||
var that = $(this).data('blueimp-fileupload') ||
|
||||
$(this).data('fileupload'),
|
||||
removeNode = function () {
|
||||
that._transition(data.context).done(
|
||||
function () {
|
||||
$(this).remove();
|
||||
that._trigger('destroyed', e, data);
|
||||
}
|
||||
);
|
||||
};
|
||||
if (data.url) {
|
||||
data.dataType = data.dataType || that.options.dataType;
|
||||
$.ajax(data).done(removeNode).fail(function () {
|
||||
that._trigger('destroyfailed', e, data);
|
||||
});
|
||||
} else {
|
||||
removeNode();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_resetFinishedDeferreds: function () {
|
||||
this._finishedUploads = [];
|
||||
},
|
||||
|
||||
_addFinishedDeferreds: function (deferred) {
|
||||
if (!deferred) {
|
||||
deferred = $.Deferred();
|
||||
}
|
||||
this._finishedUploads.push(deferred);
|
||||
return deferred;
|
||||
},
|
||||
|
||||
_getFinishedDeferreds: function () {
|
||||
return this._finishedUploads;
|
||||
},
|
||||
|
||||
// Link handler, that allows to download files
|
||||
// by drag & drop of the links to the desktop:
|
||||
_enableDragToDesktop: function () {
|
||||
var link = $(this),
|
||||
url = link.prop('href'),
|
||||
name = link.prop('download'),
|
||||
type = 'application/octet-stream';
|
||||
link.bind('dragstart', function (e) {
|
||||
try {
|
||||
e.originalEvent.dataTransfer.setData(
|
||||
'DownloadURL',
|
||||
[type, name, url].join(':')
|
||||
);
|
||||
} catch (ignore) {}
|
||||
});
|
||||
},
|
||||
|
||||
_formatFileSize: function (bytes) {
|
||||
if (typeof bytes !== 'number') {
|
||||
return '';
|
||||
}
|
||||
if (bytes >= 1000000000) {
|
||||
return (bytes / 1000000000).toFixed(2) + ' GB';
|
||||
}
|
||||
if (bytes >= 1000000) {
|
||||
return (bytes / 1000000).toFixed(2) + ' MB';
|
||||
}
|
||||
return (bytes / 1000).toFixed(2) + ' KB';
|
||||
},
|
||||
|
||||
_formatBitrate: function (bits) {
|
||||
if (typeof bits !== 'number') {
|
||||
return '';
|
||||
}
|
||||
if (bits >= 1000000000) {
|
||||
return (bits / 1000000000).toFixed(2) + ' Gbit/s';
|
||||
}
|
||||
if (bits >= 1000000) {
|
||||
return (bits / 1000000).toFixed(2) + ' Mbit/s';
|
||||
}
|
||||
if (bits >= 1000) {
|
||||
return (bits / 1000).toFixed(2) + ' kbit/s';
|
||||
}
|
||||
return bits.toFixed(2) + ' bit/s';
|
||||
},
|
||||
|
||||
_formatTime: function (seconds) {
|
||||
var date = new Date(seconds * 1000),
|
||||
days = Math.floor(seconds / 86400);
|
||||
days = days ? days + 'd ' : '';
|
||||
return days +
|
||||
('0' + date.getUTCHours()).slice(-2) + ':' +
|
||||
('0' + date.getUTCMinutes()).slice(-2) + ':' +
|
||||
('0' + date.getUTCSeconds()).slice(-2);
|
||||
},
|
||||
|
||||
_formatPercentage: function (floatValue) {
|
||||
return (floatValue * 100).toFixed(2) + ' %';
|
||||
},
|
||||
|
||||
_renderExtendedProgress: function (data) {
|
||||
return this._formatBitrate(data.bitrate) + ' | ' +
|
||||
this._formatTime(
|
||||
(data.total - data.loaded) * 8 / data.bitrate
|
||||
) + ' | ' +
|
||||
this._formatPercentage(
|
||||
data.loaded / data.total
|
||||
) + ' | ' +
|
||||
this._formatFileSize(data.loaded) + ' / ' +
|
||||
this._formatFileSize(data.total);
|
||||
},
|
||||
|
||||
_renderTemplate: function (func, files) {
|
||||
if (!func) {
|
||||
return $();
|
||||
}
|
||||
var result = func({
|
||||
files: files,
|
||||
formatFileSize: this._formatFileSize,
|
||||
options: this.options
|
||||
});
|
||||
if (result instanceof $) {
|
||||
return result;
|
||||
}
|
||||
return $(this.options.templatesContainer).html(result).children();
|
||||
},
|
||||
|
||||
_renderPreviews: function (data) {
|
||||
data.context.find('.preview').each(function (index, elm) {
|
||||
$(elm).append(data.files[index].preview);
|
||||
});
|
||||
},
|
||||
|
||||
_renderUpload: function (files) {
|
||||
return this._renderTemplate(
|
||||
this.options.uploadTemplate,
|
||||
files
|
||||
);
|
||||
},
|
||||
|
||||
_renderDownload: function (files) {
|
||||
return this._renderTemplate(
|
||||
this.options.downloadTemplate,
|
||||
files
|
||||
).find('a[download]').each(this._enableDragToDesktop).end();
|
||||
},
|
||||
|
||||
_startHandler: function (e) {
|
||||
e.preventDefault();
|
||||
var button = $(e.currentTarget),
|
||||
template = button.closest('.template-upload'),
|
||||
data = template.data('data');
|
||||
button.prop('disabled', true);
|
||||
if (data && data.submit) {
|
||||
data.submit();
|
||||
}
|
||||
},
|
||||
|
||||
_cancelHandler: function (e) {
|
||||
e.preventDefault();
|
||||
var template = $(e.currentTarget)
|
||||
.closest('.template-upload,.template-download'),
|
||||
data = template.data('data') || {};
|
||||
data.context = data.context || template;
|
||||
if (data.abort) {
|
||||
data.abort();
|
||||
} else {
|
||||
data.errorThrown = 'abort';
|
||||
this._trigger('fail', e, data);
|
||||
}
|
||||
},
|
||||
|
||||
_deleteHandler: function (e) {
|
||||
e.preventDefault();
|
||||
var button = $(e.currentTarget);
|
||||
this._trigger('destroy', e, $.extend({
|
||||
context: button.closest('.template-download'),
|
||||
type: 'DELETE'
|
||||
}, button.data()));
|
||||
},
|
||||
|
||||
_forceReflow: function (node) {
|
||||
return $.support.transition && node.length &&
|
||||
node[0].offsetWidth;
|
||||
},
|
||||
|
||||
_transition: function (node) {
|
||||
var dfd = $.Deferred();
|
||||
if ($.support.transition && node.hasClass('fade') && node.is(':visible')) {
|
||||
node.bind(
|
||||
$.support.transition.end,
|
||||
function (e) {
|
||||
// Make sure we don't respond to other transitions events
|
||||
// in the container element, e.g. from button elements:
|
||||
if (e.target === node[0]) {
|
||||
node.unbind($.support.transition.end);
|
||||
dfd.resolveWith(node);
|
||||
}
|
||||
}
|
||||
).toggleClass('in');
|
||||
} else {
|
||||
node.toggleClass('in');
|
||||
dfd.resolveWith(node);
|
||||
}
|
||||
return dfd;
|
||||
},
|
||||
|
||||
_initButtonBarEventHandlers: function () {
|
||||
var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),
|
||||
filesList = this.options.filesContainer;
|
||||
this._on(fileUploadButtonBar.find('.start'), {
|
||||
click: function (e) {
|
||||
e.preventDefault();
|
||||
filesList.find('.start').click();
|
||||
}
|
||||
});
|
||||
this._on(fileUploadButtonBar.find('.cancel'), {
|
||||
click: function (e) {
|
||||
e.preventDefault();
|
||||
filesList.find('.cancel').click();
|
||||
}
|
||||
});
|
||||
this._on(fileUploadButtonBar.find('.delete'), {
|
||||
click: function (e) {
|
||||
e.preventDefault();
|
||||
filesList.find('.toggle:checked')
|
||||
.closest('.template-download')
|
||||
.find('.delete').click();
|
||||
fileUploadButtonBar.find('.toggle')
|
||||
.prop('checked', false);
|
||||
}
|
||||
});
|
||||
this._on(fileUploadButtonBar.find('.toggle'), {
|
||||
change: function (e) {
|
||||
filesList.find('.toggle').prop(
|
||||
'checked',
|
||||
$(e.currentTarget).is(':checked')
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_destroyButtonBarEventHandlers: function () {
|
||||
this._off(
|
||||
this.element.find('.fileupload-buttonbar')
|
||||
.find('.start, .cancel, .delete'),
|
||||
'click'
|
||||
);
|
||||
this._off(
|
||||
this.element.find('.fileupload-buttonbar .toggle'),
|
||||
'change.'
|
||||
);
|
||||
},
|
||||
|
||||
_initEventHandlers: function () {
|
||||
this._super();
|
||||
this._on(this.options.filesContainer, {
|
||||
'click .start': this._startHandler,
|
||||
'click .cancel': this._cancelHandler,
|
||||
'click .delete': this._deleteHandler
|
||||
});
|
||||
this._initButtonBarEventHandlers();
|
||||
},
|
||||
|
||||
_destroyEventHandlers: function () {
|
||||
this._destroyButtonBarEventHandlers();
|
||||
this._off(this.options.filesContainer, 'click');
|
||||
this._super();
|
||||
},
|
||||
|
||||
_enableFileInputButton: function () {
|
||||
this.element.find('.fileinput-button input')
|
||||
.prop('disabled', false)
|
||||
.parent().removeClass('disabled');
|
||||
},
|
||||
|
||||
_disableFileInputButton: function () {
|
||||
this.element.find('.fileinput-button input')
|
||||
.prop('disabled', true)
|
||||
.parent().addClass('disabled');
|
||||
},
|
||||
|
||||
_initTemplates: function () {
|
||||
var options = this.options;
|
||||
options.templatesContainer = this.document[0].createElement(
|
||||
options.filesContainer.prop('nodeName')
|
||||
);
|
||||
if (tmpl) {
|
||||
if (options.uploadTemplateId) {
|
||||
options.uploadTemplate = tmpl(options.uploadTemplateId);
|
||||
}
|
||||
if (options.downloadTemplateId) {
|
||||
options.downloadTemplate = tmpl(options.downloadTemplateId);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_initFilesContainer: function () {
|
||||
var options = this.options;
|
||||
if (options.filesContainer === undefined) {
|
||||
options.filesContainer = this.element.find('.files');
|
||||
} else if (!(options.filesContainer instanceof $)) {
|
||||
options.filesContainer = $(options.filesContainer);
|
||||
}
|
||||
},
|
||||
|
||||
_initSpecialOptions: function () {
|
||||
this._super();
|
||||
this._initFilesContainer();
|
||||
this._initTemplates();
|
||||
},
|
||||
|
||||
_create: function () {
|
||||
this._super();
|
||||
this._resetFinishedDeferreds();
|
||||
if (!$.support.fileInput) {
|
||||
this._disableFileInputButton();
|
||||
}
|
||||
},
|
||||
|
||||
enable: function () {
|
||||
var wasDisabled = false;
|
||||
if (this.options.disabled) {
|
||||
wasDisabled = true;
|
||||
}
|
||||
this._super();
|
||||
if (wasDisabled) {
|
||||
this.element.find('input, button').prop('disabled', false);
|
||||
this._enableFileInputButton();
|
||||
}
|
||||
},
|
||||
|
||||
disable: function () {
|
||||
if (!this.options.disabled) {
|
||||
this.element.find('input, button').prop('disabled', true);
|
||||
this._disableFileInputButton();
|
||||
}
|
||||
this._super();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* jQuery File Upload Validation Plugin 1.1.3
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* global define, require, window */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'jquery',
|
||||
'./jquery.fileupload-process'
|
||||
], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(require('jquery'));
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.jQuery
|
||||
);
|
||||
}
|
||||
}(function ($) {
|
||||
'use strict';
|
||||
|
||||
// Append to the default processQueue:
|
||||
$.blueimp.fileupload.prototype.options.processQueue.push(
|
||||
{
|
||||
action: 'validate',
|
||||
// Always trigger this action,
|
||||
// even if the previous action was rejected:
|
||||
always: true,
|
||||
// Options taken from the global options map:
|
||||
acceptFileTypes: '@',
|
||||
maxFileSize: '@',
|
||||
minFileSize: '@',
|
||||
maxNumberOfFiles: '@',
|
||||
disabled: '@disableValidation'
|
||||
}
|
||||
);
|
||||
|
||||
// The File Upload Validation plugin extends the fileupload widget
|
||||
// with file validation functionality:
|
||||
$.widget('blueimp.fileupload', $.blueimp.fileupload, {
|
||||
|
||||
options: {
|
||||
/*
|
||||
// The regular expression for allowed file types, matches
|
||||
// against either file type or file name:
|
||||
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
|
||||
// The maximum allowed file size in bytes:
|
||||
maxFileSize: 10000000, // 10 MB
|
||||
// The minimum allowed file size in bytes:
|
||||
minFileSize: undefined, // No minimal file size
|
||||
// The limit of files to be uploaded:
|
||||
maxNumberOfFiles: 10,
|
||||
*/
|
||||
|
||||
// Function returning the current number of files,
|
||||
// has to be overriden for maxNumberOfFiles validation:
|
||||
getNumberOfFiles: $.noop,
|
||||
|
||||
// Error and info messages:
|
||||
messages: {
|
||||
maxNumberOfFiles: 'Maximum number of files exceeded',
|
||||
acceptFileTypes: 'File type not allowed',
|
||||
maxFileSize: 'File is too large',
|
||||
minFileSize: 'File is too small'
|
||||
}
|
||||
},
|
||||
|
||||
processActions: {
|
||||
|
||||
validate: function (data, options) {
|
||||
if (options.disabled) {
|
||||
return data;
|
||||
}
|
||||
var dfd = $.Deferred(),
|
||||
settings = this.options,
|
||||
file = data.files[data.index],
|
||||
fileSize;
|
||||
if (options.minFileSize || options.maxFileSize) {
|
||||
fileSize = file.size;
|
||||
}
|
||||
if ($.type(options.maxNumberOfFiles) === 'number' &&
|
||||
(settings.getNumberOfFiles() || 0) + data.files.length >
|
||||
options.maxNumberOfFiles) {
|
||||
file.error = settings.i18n('maxNumberOfFiles');
|
||||
} else if (options.acceptFileTypes &&
|
||||
!(options.acceptFileTypes.test(file.type) ||
|
||||
options.acceptFileTypes.test(file.name))) {
|
||||
file.error = settings.i18n('acceptFileTypes');
|
||||
} else if (fileSize > options.maxFileSize) {
|
||||
file.error = settings.i18n('maxFileSize');
|
||||
} else if ($.type(fileSize) === 'number' &&
|
||||
fileSize < options.minFileSize) {
|
||||
file.error = settings.i18n('minFileSize');
|
||||
} else {
|
||||
delete file.error;
|
||||
}
|
||||
if (file.error || data.files.error) {
|
||||
data.files.error = true;
|
||||
dfd.rejectWith(this, [data]);
|
||||
} else {
|
||||
dfd.resolveWith(this, [data]);
|
||||
}
|
||||
return dfd.promise();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* jQuery File Upload Video Preview Plugin 1.0.4
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* jshint nomen:false */
|
||||
/* global define, require, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'jquery',
|
||||
'load-image',
|
||||
'./jquery.fileupload-process'
|
||||
], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(
|
||||
require('jquery'),
|
||||
require('load-image')
|
||||
);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.jQuery,
|
||||
window.loadImage
|
||||
);
|
||||
}
|
||||
}(function ($, loadImage) {
|
||||
'use strict';
|
||||
|
||||
// Prepend to the default processQueue:
|
||||
$.blueimp.fileupload.prototype.options.processQueue.unshift(
|
||||
{
|
||||
action: 'loadVideo',
|
||||
// Use the action as prefix for the "@" options:
|
||||
prefix: true,
|
||||
fileTypes: '@',
|
||||
maxFileSize: '@',
|
||||
disabled: '@disableVideoPreview'
|
||||
},
|
||||
{
|
||||
action: 'setVideo',
|
||||
name: '@videoPreviewName',
|
||||
disabled: '@disableVideoPreview'
|
||||
}
|
||||
);
|
||||
|
||||
// The File Upload Video Preview plugin extends the fileupload widget
|
||||
// with video preview functionality:
|
||||
$.widget('blueimp.fileupload', $.blueimp.fileupload, {
|
||||
|
||||
options: {
|
||||
// The regular expression for the types of video files to load,
|
||||
// matched against the file type:
|
||||
loadVideoFileTypes: /^video\/.*$/
|
||||
},
|
||||
|
||||
_videoElement: document.createElement('video'),
|
||||
|
||||
processActions: {
|
||||
|
||||
// Loads the video file given via data.files and data.index
|
||||
// as video element if the browser supports playing it.
|
||||
// Accepts the options fileTypes (regular expression)
|
||||
// and maxFileSize (integer) to limit the files to load:
|
||||
loadVideo: function (data, options) {
|
||||
if (options.disabled) {
|
||||
return data;
|
||||
}
|
||||
var file = data.files[data.index],
|
||||
url,
|
||||
video;
|
||||
if (this._videoElement.canPlayType &&
|
||||
this._videoElement.canPlayType(file.type) &&
|
||||
($.type(options.maxFileSize) !== 'number' ||
|
||||
file.size <= options.maxFileSize) &&
|
||||
(!options.fileTypes ||
|
||||
options.fileTypes.test(file.type))) {
|
||||
url = loadImage.createObjectURL(file);
|
||||
if (url) {
|
||||
video = this._videoElement.cloneNode(false);
|
||||
video.src = url;
|
||||
video.controls = true;
|
||||
data.video = video;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
// Sets the video element as a property of the file object:
|
||||
setVideo: function (data, options) {
|
||||
if (data.video && !options.disabled) {
|
||||
data.files[data.index][options.name || 'preview'] = data.video;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* jQuery Iframe Transport Plugin 1.8.3
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* global define, require, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(require('jquery'));
|
||||
} 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 four 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}]
|
||||
// options.initialIframeSrc: the URL of the initial iframe src,
|
||||
// by default set to "javascript:false;"
|
||||
$.ajaxTransport('iframe', function (options) {
|
||||
if (options.async) {
|
||||
// javascript:false as initial iframe src
|
||||
// prevents warning popups on HTTPS in IE6:
|
||||
/*jshint scripturl: true */
|
||||
var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
|
||||
/*jshint scripturl: false */
|
||||
form,
|
||||
iframe,
|
||||
addParamChar;
|
||||
return {
|
||||
send: function (_, completeCallback) {
|
||||
form = $('<form style="display:none;"></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';
|
||||
}
|
||||
// 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:
|
||||
counter += 1;
|
||||
iframe = $(
|
||||
'<iframe src="' + initialIframeSrc +
|
||||
'" name="iframe-transport-' + counter + '"></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):
|
||||
$('<iframe src="' + initialIframeSrc + '"></iframe>')
|
||||
.appendTo(form);
|
||||
window.setTimeout(function () {
|
||||
// Removing the form in a setTimeout call
|
||||
// allows Chrome's developer tools to display
|
||||
// the response result
|
||||
form.remove();
|
||||
}, 0);
|
||||
});
|
||||
form
|
||||
.prop('target', iframe.prop('name'))
|
||||
.prop('action', options.url)
|
||||
.prop('method', options.type);
|
||||
if (options.formData) {
|
||||
$.each(options.formData, function (index, field) {
|
||||
$('<input type="hidden"/>')
|
||||
.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');
|
||||
// Remove the HTML5 form attribute from the input(s):
|
||||
options.fileInput.removeAttr('form');
|
||||
}
|
||||
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]);
|
||||
// Restore the original name and form properties:
|
||||
$(input)
|
||||
.prop('name', clone.prop('name'))
|
||||
.attr('form', clone.attr('form'));
|
||||
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', initialIframeSrc);
|
||||
}
|
||||
if (form) {
|
||||
form.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// The iframe transport returns the iframe content document as response.
|
||||
// The following adds converters from iframe to text, json, html, xml
|
||||
// and script.
|
||||
// Please note that the Content-Type for JSON responses has to be text/plain
|
||||
// or text/html, if the browser doesn't include application/json in the
|
||||
// Accept header, else IE will show a download dialog.
|
||||
// The Content-Type for XML responses on the other hand has to be always
|
||||
// application/xml or text/xml, so IE properly parses the XML response.
|
||||
// See also
|
||||
// https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation
|
||||
$.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 xml': function (iframe) {
|
||||
var xmlDoc = iframe && iframe[0];
|
||||
return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc :
|
||||
$.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) ||
|
||||
$(xmlDoc.body).html());
|
||||
},
|
||||
'iframe script': function (iframe) {
|
||||
return iframe && $.globalEval($(iframe[0].body).text());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* jQuery File Upload User Interface Plugin 9.6.1
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* jshint nomen:false */
|
||||
/* global define, require, window */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'jquery',
|
||||
'../jquery.fileupload'
|
||||
], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS:
|
||||
factory(
|
||||
require('jquery'),
|
||||
require('../jquery.fileupload')
|
||||
);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.jQuery
|
||||
);
|
||||
}
|
||||
}(function ($) {
|
||||
'use strict';
|
||||
|
||||
// The UI version extends the file upload widget
|
||||
// and adds complete user interface interaction:
|
||||
$.widget('blueimp.fileupload', $.blueimp.fileupload, {
|
||||
getUploadButton: function() {
|
||||
var uploadButton = $('<button/>')
|
||||
.addClass('btn')
|
||||
.prop('disabled', true)
|
||||
.text('Processing...')
|
||||
.on('click', function () {
|
||||
var $this = $(this),
|
||||
data = $this.data();
|
||||
$this
|
||||
.off('click')
|
||||
.text('Abort')
|
||||
.on('click', function () {
|
||||
$this.remove();
|
||||
data.abort();
|
||||
});
|
||||
data.submit().always(function () {
|
||||
$this.remove();
|
||||
});
|
||||
});
|
||||
return uploadButton;
|
||||
},
|
||||
|
||||
// Bind event handler to the client plugin events
|
||||
initTheme: function (theme) {
|
||||
var $this = this.element;
|
||||
var low = theme.toLowerCase();
|
||||
if ($this) {
|
||||
if (low == "basic")
|
||||
this._initBasicTheme($this);
|
||||
else if (low == "basicplus")
|
||||
this._initBasicPlusTheme($this);
|
||||
else if ((low == "basicplusui") || (low == "jqueryui"))
|
||||
this._initBasicPlusUITheme($this);
|
||||
return $this;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// Bind event handlers in Basic Plus Theme
|
||||
_initBasicTheme: function($this) {
|
||||
$this.on('fileuploaddone', function (e, data) {
|
||||
$.each(data.result.files, function (index, file) {
|
||||
$('<p/>').text(file.name).appendTo('#files');
|
||||
});
|
||||
})
|
||||
.on('fileuploadprogressall', function (e, data) {
|
||||
var progress = parseInt(data.loaded / data.total * 100, 10);
|
||||
$('#progress .progress-bar').css(
|
||||
'width',
|
||||
progress + '%'
|
||||
);
|
||||
})
|
||||
.prop('disabled', !$.support.fileInput)
|
||||
.parent().addClass($.support.fileInput ? undefined : 'disabled')
|
||||
},
|
||||
|
||||
// Bind event handlers in Basic Plus Theme
|
||||
_initBasicPlusTheme: function($this) {
|
||||
$this.on('fileuploadadd', function (e, data) {
|
||||
var $widget = $(e.target).data('blueimp-fileupload');
|
||||
var uploadButton = $widget.getUploadButton();
|
||||
data.context = $('<div/>').appendTo('#files');
|
||||
$.each(data.files, function (index, file) {
|
||||
var node = $('<p/>')
|
||||
.append($('<span/>').text(file.name));
|
||||
if (!index) {
|
||||
node
|
||||
.append('<br>')
|
||||
.append(uploadButton.clone(true).data(data));
|
||||
}
|
||||
node.appendTo(data.context);
|
||||
});
|
||||
})
|
||||
|
||||
.on('fileuploadprocessalways', function (e, data) {
|
||||
var index = data.index,
|
||||
file = data.files[index],
|
||||
node = $(data.context.children()[index]);
|
||||
if (file.preview) {
|
||||
node
|
||||
.prepend('<br>')
|
||||
.prepend(file.preview);
|
||||
}
|
||||
if (file.error) {
|
||||
node
|
||||
.append('<br>')
|
||||
.append(file.error);
|
||||
}
|
||||
if (index + 1 === data.files.length) {
|
||||
data.context.find('button')
|
||||
.text('Upload')
|
||||
.prop('disabled', !!data.files.error);
|
||||
}
|
||||
})
|
||||
|
||||
.on('fileuploadprogressall', function (e, data) {
|
||||
var progress = parseInt(data.loaded / data.total * 100, 10);
|
||||
$('#progress .bar').css(
|
||||
'width',
|
||||
progress + '%'
|
||||
);
|
||||
})
|
||||
|
||||
.on('fileuploaddone', function (e, data) {
|
||||
$.each(data.result.files, function (index, file) {
|
||||
var link = $('<a>')
|
||||
.attr('target', '_blank')
|
||||
.prop('href', file.url);
|
||||
$(data.context.children()[index])
|
||||
.wrap(link);
|
||||
});
|
||||
})
|
||||
|
||||
.on('fileuploadfail', function (e, data) {
|
||||
$.each(data.result.files, function (index, file) {
|
||||
var error = $('<span/>').text(file.error);
|
||||
$(data.context.children()[index])
|
||||
.append('<br>')
|
||||
.append(error);
|
||||
});
|
||||
})
|
||||
|
||||
.prop('disabled', !$.support.fileInput)
|
||||
.parent().addClass($.support.fileInput ? undefined : 'disabled');
|
||||
},
|
||||
|
||||
// Bind event handlers in Basic Plus UI theme
|
||||
_initBasicPlusUITheme: function($this) {
|
||||
$this
|
||||
.prop('disabled', !$.support.fileInput)
|
||||
.parent().addClass($.support.fileInput ? undefined : 'disabled')
|
||||
},
|
||||
|
||||
|
||||
})
|
||||
}))
|
||||
@@ -0,0 +1,563 @@
|
||||
/*! jQuery UI - v1.11.1+CommonJS - 2014-09-17
|
||||
* http://jqueryui.com
|
||||
* Includes: widget.js
|
||||
* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
|
||||
|
||||
(function( factory ) {
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
define([ "jquery" ], factory );
|
||||
|
||||
} else if (typeof exports === "object") {
|
||||
// Node/CommonJS:
|
||||
factory(require("jquery"));
|
||||
|
||||
} else {
|
||||
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
}(function( $ ) {
|
||||
/*!
|
||||
* jQuery UI Widget 1.11.1
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright 2014 jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://api.jqueryui.com/jQuery.widget/
|
||||
*/
|
||||
|
||||
|
||||
var widget_uuid = 0,
|
||||
widget_slice = Array.prototype.slice;
|
||||
|
||||
$.cleanData = (function( orig ) {
|
||||
return function( elems ) {
|
||||
var events, elem, i;
|
||||
for ( i = 0; (elem = elems[i]) != null; i++ ) {
|
||||
try {
|
||||
|
||||
// Only trigger remove when necessary to save time
|
||||
events = $._data( elem, "events" );
|
||||
if ( events && events.remove ) {
|
||||
$( elem ).triggerHandler( "remove" );
|
||||
}
|
||||
|
||||
// http://bugs.jquery.com/ticket/8235
|
||||
} catch( e ) {}
|
||||
}
|
||||
orig( elems );
|
||||
};
|
||||
})( $.cleanData );
|
||||
|
||||
$.widget = function( name, base, prototype ) {
|
||||
var fullName, existingConstructor, constructor, basePrototype,
|
||||
// proxiedPrototype allows the provided prototype to remain unmodified
|
||||
// so that it can be used as a mixin for multiple widgets (#8876)
|
||||
proxiedPrototype = {},
|
||||
namespace = name.split( "." )[ 0 ];
|
||||
|
||||
name = name.split( "." )[ 1 ];
|
||||
fullName = namespace + "-" + name;
|
||||
|
||||
if ( !prototype ) {
|
||||
prototype = base;
|
||||
base = $.Widget;
|
||||
}
|
||||
|
||||
// create selector for plugin
|
||||
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
|
||||
return !!$.data( elem, fullName );
|
||||
};
|
||||
|
||||
$[ namespace ] = $[ namespace ] || {};
|
||||
existingConstructor = $[ namespace ][ name ];
|
||||
constructor = $[ namespace ][ name ] = function( options, element ) {
|
||||
// allow instantiation without "new" keyword
|
||||
if ( !this._createWidget ) {
|
||||
return new constructor( options, element );
|
||||
}
|
||||
|
||||
// allow instantiation without initializing for simple inheritance
|
||||
// must use "new" keyword (the code above always passes args)
|
||||
if ( arguments.length ) {
|
||||
this._createWidget( options, element );
|
||||
}
|
||||
};
|
||||
// extend with the existing constructor to carry over any static properties
|
||||
$.extend( constructor, existingConstructor, {
|
||||
version: prototype.version,
|
||||
// copy the object used to create the prototype in case we need to
|
||||
// redefine the widget later
|
||||
_proto: $.extend( {}, prototype ),
|
||||
// track widgets that inherit from this widget in case this widget is
|
||||
// redefined after a widget inherits from it
|
||||
_childConstructors: []
|
||||
});
|
||||
|
||||
basePrototype = new base();
|
||||
// we need to make the options hash a property directly on the new instance
|
||||
// otherwise we'll modify the options hash on the prototype that we're
|
||||
// inheriting from
|
||||
basePrototype.options = $.widget.extend( {}, basePrototype.options );
|
||||
$.each( prototype, function( prop, value ) {
|
||||
if ( !$.isFunction( value ) ) {
|
||||
proxiedPrototype[ prop ] = value;
|
||||
return;
|
||||
}
|
||||
proxiedPrototype[ prop ] = (function() {
|
||||
var _super = function() {
|
||||
return base.prototype[ prop ].apply( this, arguments );
|
||||
},
|
||||
_superApply = function( args ) {
|
||||
return base.prototype[ prop ].apply( this, args );
|
||||
};
|
||||
return function() {
|
||||
var __super = this._super,
|
||||
__superApply = this._superApply,
|
||||
returnValue;
|
||||
|
||||
this._super = _super;
|
||||
this._superApply = _superApply;
|
||||
|
||||
returnValue = value.apply( this, arguments );
|
||||
|
||||
this._super = __super;
|
||||
this._superApply = __superApply;
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
})();
|
||||
});
|
||||
constructor.prototype = $.widget.extend( basePrototype, {
|
||||
// TODO: remove support for widgetEventPrefix
|
||||
// always use the name + a colon as the prefix, e.g., draggable:start
|
||||
// don't prefix for widgets that aren't DOM-based
|
||||
widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
|
||||
}, proxiedPrototype, {
|
||||
constructor: constructor,
|
||||
namespace: namespace,
|
||||
widgetName: name,
|
||||
widgetFullName: fullName
|
||||
});
|
||||
|
||||
// If this widget is being redefined then we need to find all widgets that
|
||||
// are inheriting from it and redefine all of them so that they inherit from
|
||||
// the new version of this widget. We're essentially trying to replace one
|
||||
// level in the prototype chain.
|
||||
if ( existingConstructor ) {
|
||||
$.each( existingConstructor._childConstructors, function( i, child ) {
|
||||
var childPrototype = child.prototype;
|
||||
|
||||
// redefine the child widget using the same prototype that was
|
||||
// originally used, but inherit from the new version of the base
|
||||
$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
|
||||
});
|
||||
// remove the list of existing child constructors from the old constructor
|
||||
// so the old child constructors can be garbage collected
|
||||
delete existingConstructor._childConstructors;
|
||||
} else {
|
||||
base._childConstructors.push( constructor );
|
||||
}
|
||||
|
||||
$.widget.bridge( name, constructor );
|
||||
|
||||
return constructor;
|
||||
};
|
||||
|
||||
$.widget.extend = function( target ) {
|
||||
var input = widget_slice.call( arguments, 1 ),
|
||||
inputIndex = 0,
|
||||
inputLength = input.length,
|
||||
key,
|
||||
value;
|
||||
for ( ; inputIndex < inputLength; inputIndex++ ) {
|
||||
for ( key in input[ inputIndex ] ) {
|
||||
value = input[ inputIndex ][ key ];
|
||||
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
|
||||
// Clone objects
|
||||
if ( $.isPlainObject( value ) ) {
|
||||
target[ key ] = $.isPlainObject( target[ key ] ) ?
|
||||
$.widget.extend( {}, target[ key ], value ) :
|
||||
// Don't extend strings, arrays, etc. with objects
|
||||
$.widget.extend( {}, value );
|
||||
// Copy everything else by reference
|
||||
} else {
|
||||
target[ key ] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
|
||||
$.widget.bridge = function( name, object ) {
|
||||
var fullName = object.prototype.widgetFullName || name;
|
||||
$.fn[ name ] = function( options ) {
|
||||
var isMethodCall = typeof options === "string",
|
||||
args = widget_slice.call( arguments, 1 ),
|
||||
returnValue = this;
|
||||
|
||||
// allow multiple hashes to be passed on init
|
||||
options = !isMethodCall && args.length ?
|
||||
$.widget.extend.apply( null, [ options ].concat(args) ) :
|
||||
options;
|
||||
|
||||
if ( isMethodCall ) {
|
||||
this.each(function() {
|
||||
var methodValue,
|
||||
instance = $.data( this, fullName );
|
||||
if ( options === "instance" ) {
|
||||
returnValue = instance;
|
||||
return false;
|
||||
}
|
||||
if ( !instance ) {
|
||||
return $.error( "cannot call methods on " + name + " prior to initialization; " +
|
||||
"attempted to call method '" + options + "'" );
|
||||
}
|
||||
if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
|
||||
return $.error( "no such method '" + options + "' for " + name + " widget instance" );
|
||||
}
|
||||
methodValue = instance[ options ].apply( instance, args );
|
||||
if ( methodValue !== instance && methodValue !== undefined ) {
|
||||
returnValue = methodValue && methodValue.jquery ?
|
||||
returnValue.pushStack( methodValue.get() ) :
|
||||
methodValue;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.each(function() {
|
||||
var instance = $.data( this, fullName );
|
||||
if ( instance ) {
|
||||
instance.option( options || {} );
|
||||
if ( instance._init ) {
|
||||
instance._init();
|
||||
}
|
||||
} else {
|
||||
$.data( this, fullName, new object( options, this ) );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
};
|
||||
|
||||
$.Widget = function( /* options, element */ ) {};
|
||||
$.Widget._childConstructors = [];
|
||||
|
||||
$.Widget.prototype = {
|
||||
widgetName: "widget",
|
||||
widgetEventPrefix: "",
|
||||
defaultElement: "<div>",
|
||||
options: {
|
||||
disabled: false,
|
||||
|
||||
// callbacks
|
||||
create: null
|
||||
},
|
||||
_createWidget: function( options, element ) {
|
||||
element = $( element || this.defaultElement || this )[ 0 ];
|
||||
this.element = $( element );
|
||||
this.uuid = widget_uuid++;
|
||||
this.eventNamespace = "." + this.widgetName + this.uuid;
|
||||
this.options = $.widget.extend( {},
|
||||
this.options,
|
||||
this._getCreateOptions(),
|
||||
options );
|
||||
|
||||
this.bindings = $();
|
||||
this.hoverable = $();
|
||||
this.focusable = $();
|
||||
|
||||
if ( element !== this ) {
|
||||
$.data( element, this.widgetFullName, this );
|
||||
this._on( true, this.element, {
|
||||
remove: function( event ) {
|
||||
if ( event.target === element ) {
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.document = $( element.style ?
|
||||
// element within the document
|
||||
element.ownerDocument :
|
||||
// element is window or document
|
||||
element.document || element );
|
||||
this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
|
||||
}
|
||||
|
||||
this._create();
|
||||
this._trigger( "create", null, this._getCreateEventData() );
|
||||
this._init();
|
||||
},
|
||||
_getCreateOptions: $.noop,
|
||||
_getCreateEventData: $.noop,
|
||||
_create: $.noop,
|
||||
_init: $.noop,
|
||||
|
||||
destroy: function() {
|
||||
this._destroy();
|
||||
// we can probably remove the unbind calls in 2.0
|
||||
// all event bindings should go through this._on()
|
||||
this.element
|
||||
.unbind( this.eventNamespace )
|
||||
.removeData( this.widgetFullName )
|
||||
// support: jquery <1.6.3
|
||||
// http://bugs.jquery.com/ticket/9413
|
||||
.removeData( $.camelCase( this.widgetFullName ) );
|
||||
this.widget()
|
||||
.unbind( this.eventNamespace )
|
||||
.removeAttr( "aria-disabled" )
|
||||
.removeClass(
|
||||
this.widgetFullName + "-disabled " +
|
||||
"ui-state-disabled" );
|
||||
|
||||
// clean up events and states
|
||||
this.bindings.unbind( this.eventNamespace );
|
||||
this.hoverable.removeClass( "ui-state-hover" );
|
||||
this.focusable.removeClass( "ui-state-focus" );
|
||||
},
|
||||
_destroy: $.noop,
|
||||
|
||||
widget: function() {
|
||||
return this.element;
|
||||
},
|
||||
|
||||
option: function( key, value ) {
|
||||
var options = key,
|
||||
parts,
|
||||
curOption,
|
||||
i;
|
||||
|
||||
if ( arguments.length === 0 ) {
|
||||
// don't return a reference to the internal hash
|
||||
return $.widget.extend( {}, this.options );
|
||||
}
|
||||
|
||||
if ( typeof key === "string" ) {
|
||||
// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
|
||||
options = {};
|
||||
parts = key.split( "." );
|
||||
key = parts.shift();
|
||||
if ( parts.length ) {
|
||||
curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
|
||||
for ( i = 0; i < parts.length - 1; i++ ) {
|
||||
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
|
||||
curOption = curOption[ parts[ i ] ];
|
||||
}
|
||||
key = parts.pop();
|
||||
if ( arguments.length === 1 ) {
|
||||
return curOption[ key ] === undefined ? null : curOption[ key ];
|
||||
}
|
||||
curOption[ key ] = value;
|
||||
} else {
|
||||
if ( arguments.length === 1 ) {
|
||||
return this.options[ key ] === undefined ? null : this.options[ key ];
|
||||
}
|
||||
options[ key ] = value;
|
||||
}
|
||||
}
|
||||
|
||||
this._setOptions( options );
|
||||
|
||||
return this;
|
||||
},
|
||||
_setOptions: function( options ) {
|
||||
var key;
|
||||
|
||||
for ( key in options ) {
|
||||
this._setOption( key, options[ key ] );
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
_setOption: function( key, value ) {
|
||||
this.options[ key ] = value;
|
||||
|
||||
if ( key === "disabled" ) {
|
||||
this.widget()
|
||||
.toggleClass( this.widgetFullName + "-disabled", !!value );
|
||||
|
||||
// If the widget is becoming disabled, then nothing is interactive
|
||||
if ( value ) {
|
||||
this.hoverable.removeClass( "ui-state-hover" );
|
||||
this.focusable.removeClass( "ui-state-focus" );
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
enable: function() {
|
||||
return this._setOptions({ disabled: false });
|
||||
},
|
||||
disable: function() {
|
||||
return this._setOptions({ disabled: true });
|
||||
},
|
||||
|
||||
_on: function( suppressDisabledCheck, element, handlers ) {
|
||||
var delegateElement,
|
||||
instance = this;
|
||||
|
||||
// no suppressDisabledCheck flag, shuffle arguments
|
||||
if ( typeof suppressDisabledCheck !== "boolean" ) {
|
||||
handlers = element;
|
||||
element = suppressDisabledCheck;
|
||||
suppressDisabledCheck = false;
|
||||
}
|
||||
|
||||
// no element argument, shuffle and use this.element
|
||||
if ( !handlers ) {
|
||||
handlers = element;
|
||||
element = this.element;
|
||||
delegateElement = this.widget();
|
||||
} else {
|
||||
element = delegateElement = $( element );
|
||||
this.bindings = this.bindings.add( element );
|
||||
}
|
||||
|
||||
$.each( handlers, function( event, handler ) {
|
||||
function handlerProxy() {
|
||||
// allow widgets to customize the disabled handling
|
||||
// - disabled as an array instead of boolean
|
||||
// - disabled class as method for disabling individual parts
|
||||
if ( !suppressDisabledCheck &&
|
||||
( instance.options.disabled === true ||
|
||||
$( this ).hasClass( "ui-state-disabled" ) ) ) {
|
||||
return;
|
||||
}
|
||||
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
||||
.apply( instance, arguments );
|
||||
}
|
||||
|
||||
// copy the guid so direct unbinding works
|
||||
if ( typeof handler !== "string" ) {
|
||||
handlerProxy.guid = handler.guid =
|
||||
handler.guid || handlerProxy.guid || $.guid++;
|
||||
}
|
||||
|
||||
var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
|
||||
eventName = match[1] + instance.eventNamespace,
|
||||
selector = match[2];
|
||||
if ( selector ) {
|
||||
delegateElement.delegate( selector, eventName, handlerProxy );
|
||||
} else {
|
||||
element.bind( eventName, handlerProxy );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_off: function( element, eventName ) {
|
||||
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
|
||||
element.unbind( eventName ).undelegate( eventName );
|
||||
},
|
||||
|
||||
_delay: function( handler, delay ) {
|
||||
function handlerProxy() {
|
||||
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
||||
.apply( instance, arguments );
|
||||
}
|
||||
var instance = this;
|
||||
return setTimeout( handlerProxy, delay || 0 );
|
||||
},
|
||||
|
||||
_hoverable: function( element ) {
|
||||
this.hoverable = this.hoverable.add( element );
|
||||
this._on( element, {
|
||||
mouseenter: function( event ) {
|
||||
$( event.currentTarget ).addClass( "ui-state-hover" );
|
||||
},
|
||||
mouseleave: function( event ) {
|
||||
$( event.currentTarget ).removeClass( "ui-state-hover" );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_focusable: function( element ) {
|
||||
this.focusable = this.focusable.add( element );
|
||||
this._on( element, {
|
||||
focusin: function( event ) {
|
||||
$( event.currentTarget ).addClass( "ui-state-focus" );
|
||||
},
|
||||
focusout: function( event ) {
|
||||
$( event.currentTarget ).removeClass( "ui-state-focus" );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_trigger: function( type, event, data ) {
|
||||
var prop, orig,
|
||||
callback = this.options[ type ];
|
||||
|
||||
data = data || {};
|
||||
event = $.Event( event );
|
||||
event.type = ( type === this.widgetEventPrefix ?
|
||||
type :
|
||||
this.widgetEventPrefix + type ).toLowerCase();
|
||||
// the original event may come from any element
|
||||
// so we need to reset the target on the new event
|
||||
event.target = this.element[ 0 ];
|
||||
|
||||
// copy original event properties over to the new event
|
||||
orig = event.originalEvent;
|
||||
if ( orig ) {
|
||||
for ( prop in orig ) {
|
||||
if ( !( prop in event ) ) {
|
||||
event[ prop ] = orig[ prop ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.element.trigger( event, data );
|
||||
return !( $.isFunction( callback ) &&
|
||||
callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
|
||||
event.isDefaultPrevented() );
|
||||
}
|
||||
};
|
||||
|
||||
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
|
||||
$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
|
||||
if ( typeof options === "string" ) {
|
||||
options = { effect: options };
|
||||
}
|
||||
var hasOptions,
|
||||
effectName = !options ?
|
||||
method :
|
||||
options === true || typeof options === "number" ?
|
||||
defaultEffect :
|
||||
options.effect || defaultEffect;
|
||||
options = options || {};
|
||||
if ( typeof options === "number" ) {
|
||||
options = { duration: options };
|
||||
}
|
||||
hasOptions = !$.isEmptyObject( options );
|
||||
options.complete = callback;
|
||||
if ( options.delay ) {
|
||||
element.delay( options.delay );
|
||||
}
|
||||
if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
|
||||
element[ method ]( options );
|
||||
} else if ( effectName !== method && element[ effectName ] ) {
|
||||
element[ effectName ]( options.duration, options.easing, callback );
|
||||
} else {
|
||||
element.queue(function( next ) {
|
||||
$( this )[ method ]();
|
||||
if ( callback ) {
|
||||
callback.call( element[ 0 ] );
|
||||
}
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
var widget = $.widget;
|
||||
|
||||
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "blueimp-file-upload",
|
||||
"version": "9.10.5",
|
||||
"title": "jQuery File Upload",
|
||||
"description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
|
||||
"keywords": [
|
||||
"jquery",
|
||||
"file",
|
||||
"upload",
|
||||
"widget",
|
||||
"multiple",
|
||||
"selection",
|
||||
"drag",
|
||||
"drop",
|
||||
"progress",
|
||||
"preview",
|
||||
"cross-domain",
|
||||
"cross-site",
|
||||
"chunk",
|
||||
"resume",
|
||||
"gae",
|
||||
"go",
|
||||
"python",
|
||||
"php",
|
||||
"bootstrap"
|
||||
],
|
||||
"homepage": "https://github.com/blueimp/jQuery-File-Upload",
|
||||
"author": {
|
||||
"name": "Sebastian Tschan",
|
||||
"url": "https://blueimp.net"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Sebastian Tschan",
|
||||
"url": "https://blueimp.net"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/blueimp/jQuery-File-Upload.git"
|
||||
},
|
||||
"bugs": "https://github.com/blueimp/jQuery-File-Upload/issues",
|
||||
"license": "MIT",
|
||||
"main": "js/jquery.fileupload.js",
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.5",
|
||||
"grunt-bump-build-git": "~1.1.1",
|
||||
"grunt-contrib-jshint": "~0.10.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
@charset "UTF-8";
|
||||
/*
|
||||
* blueimp Gallery Indicator CSS 1.1.0
|
||||
* https://github.com/blueimp/Gallery
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
.blueimp-gallery > .indicator {
|
||||
position: absolute;
|
||||
top: auto;
|
||||
right: 15px;
|
||||
bottom: 15px;
|
||||
left: 15px;
|
||||
margin: 0 40px;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
text-align: center;
|
||||
line-height: 10px;
|
||||
display: none;
|
||||
}
|
||||
.blueimp-gallery > .indicator > li {
|
||||
display: inline-block;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
margin: 6px 3px 0 3px;
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
border: 1px solid transparent;
|
||||
background: #ccc;
|
||||
background: rgba(255, 255, 255, 0.25) center no-repeat;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 2px #000;
|
||||
opacity: 0.5;
|
||||
cursor: pointer;
|
||||
}
|
||||
.blueimp-gallery > .indicator > li:hover,
|
||||
.blueimp-gallery > .indicator > .active {
|
||||
background-color: #fff;
|
||||
border-color: #fff;
|
||||
opacity: 1;
|
||||
}
|
||||
.blueimp-gallery-controls > .indicator {
|
||||
display: block;
|
||||
/* Fix z-index issues (controls behind slide element) on Android: */
|
||||
-webkit-transform: translateZ(0);
|
||||
-moz-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
-o-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
}
|
||||
.blueimp-gallery-single > .indicator {
|
||||
display: none;
|
||||
}
|
||||
.blueimp-gallery > .indicator {
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* IE7 fixes */
|
||||
*+html .blueimp-gallery > .indicator > li {
|
||||
display: inline;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
@charset "UTF-8";
|
||||
/*
|
||||
* blueimp Gallery Video Factory CSS 1.3.0
|
||||
* https://github.com/blueimp/Gallery
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
.blueimp-gallery > .slides > .slide > .video-content > img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
/* Prevent artifacts in Mozilla Firefox: */
|
||||
-moz-backface-visibility: hidden;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .video-content > video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .video-content > iframe {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .video-playing > iframe {
|
||||
top: 0;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .video-content > a {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
left: 0;
|
||||
margin: -64px auto 0;
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
background: url(../img/video-play.png) center no-repeat;
|
||||
opacity: 0.8;
|
||||
cursor: pointer;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .video-content > a:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .video-playing > a,
|
||||
.blueimp-gallery > .slides > .slide > .video-playing > img {
|
||||
display: none;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .video-content > video {
|
||||
display: none;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .video-playing > video {
|
||||
display: block;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .video-loading > a {
|
||||
background: url(../img/loading.gif) center no-repeat;
|
||||
background-size: 64px 64px;
|
||||
}
|
||||
|
||||
/* Replace PNGs with SVGs for capable browsers (excluding IE<9) */
|
||||
body:last-child .blueimp-gallery > .slides > .slide > .video-content:not(.video-loading) > a {
|
||||
background-image: url(../img/video-play.svg);
|
||||
}
|
||||
|
||||
/* IE7 fixes */
|
||||
*+html .blueimp-gallery > .slides > .slide > .video-content {
|
||||
height: 100%;
|
||||
}
|
||||
*+html .blueimp-gallery > .slides > .slide > .video-content > a {
|
||||
left: 50%;
|
||||
margin-left: -64px;
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
@charset "UTF-8";
|
||||
/*
|
||||
* blueimp Gallery CSS 2.11.1
|
||||
* https://github.com/blueimp/Gallery
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
.blueimp-gallery,
|
||||
.blueimp-gallery > .slides > .slide > .slide-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
/* Prevent artifacts in Mozilla Firefox: */
|
||||
-moz-backface-visibility: hidden;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .slide-content {
|
||||
margin: auto;
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
opacity: 1;
|
||||
}
|
||||
.blueimp-gallery {
|
||||
position: fixed;
|
||||
z-index: 999999;
|
||||
overflow: hidden;
|
||||
background: #000;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
opacity: 0;
|
||||
display: none;
|
||||
direction: ltr;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.blueimp-gallery-carousel {
|
||||
position: relative;
|
||||
z-index: auto;
|
||||
margin: 1em auto;
|
||||
/* Set the carousel width/height ratio to 16/9: */
|
||||
padding-bottom: 56.25%;
|
||||
box-shadow: 0 0 10px #000;
|
||||
-ms-touch-action: pan-y;
|
||||
touch-action: pan-y;
|
||||
}
|
||||
.blueimp-gallery-display {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
.blueimp-gallery > .slides {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.blueimp-gallery-carousel > .slides {
|
||||
position: absolute;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide {
|
||||
position: relative;
|
||||
float: left;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
-moz-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
-ms-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
-o-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
}
|
||||
.blueimp-gallery,
|
||||
.blueimp-gallery > .slides > .slide > .slide-content {
|
||||
-webkit-transition: opacity 0.5s linear;
|
||||
-moz-transition: opacity 0.5s linear;
|
||||
-ms-transition: opacity 0.5s linear;
|
||||
-o-transition: opacity 0.5s linear;
|
||||
transition: opacity 0.5s linear;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide-loading {
|
||||
background: url(../img/loading.gif) center no-repeat;
|
||||
background-size: 64px 64px;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide-loading > .slide-content {
|
||||
opacity: 0;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide-error {
|
||||
background: url(../img/error.png) center no-repeat;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide-error > .slide-content {
|
||||
display: none;
|
||||
}
|
||||
.blueimp-gallery > .prev,
|
||||
.blueimp-gallery > .next {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 15px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-top: -23px;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 60px;
|
||||
font-weight: 100;
|
||||
line-height: 30px;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 0 2px #000;
|
||||
text-align: center;
|
||||
background: #222;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
border: 3px solid #fff;
|
||||
-webkit-border-radius: 23px;
|
||||
-moz-border-radius: 23px;
|
||||
border-radius: 23px;
|
||||
opacity: 0.5;
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
}
|
||||
.blueimp-gallery > .next {
|
||||
left: auto;
|
||||
right: 15px;
|
||||
}
|
||||
.blueimp-gallery > .close,
|
||||
.blueimp-gallery > .title {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 15px;
|
||||
margin: 0 40px 0 0;
|
||||
font-size: 20px;
|
||||
line-height: 30px;
|
||||
color: #fff;
|
||||
text-shadow: 0 0 2px #000;
|
||||
opacity: 0.8;
|
||||
display: none;
|
||||
}
|
||||
.blueimp-gallery > .close {
|
||||
padding: 15px;
|
||||
right: 15px;
|
||||
left: auto;
|
||||
margin: -15px;
|
||||
font-size: 30px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.blueimp-gallery > .play-pause {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
bottom: 15px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background: url(../img/play-pause.png) 0 0 no-repeat;
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
display: none;
|
||||
}
|
||||
.blueimp-gallery-playing > .play-pause {
|
||||
background-position: -15px 0;
|
||||
}
|
||||
.blueimp-gallery > .prev:hover,
|
||||
.blueimp-gallery > .next:hover,
|
||||
.blueimp-gallery > .close:hover,
|
||||
.blueimp-gallery > .title:hover,
|
||||
.blueimp-gallery > .play-pause:hover {
|
||||
color: #fff;
|
||||
opacity: 1;
|
||||
}
|
||||
.blueimp-gallery-controls > .prev,
|
||||
.blueimp-gallery-controls > .next,
|
||||
.blueimp-gallery-controls > .close,
|
||||
.blueimp-gallery-controls > .title,
|
||||
.blueimp-gallery-controls > .play-pause {
|
||||
display: block;
|
||||
/* Fix z-index issues (controls behind slide element) on Android: */
|
||||
-webkit-transform: translateZ(0);
|
||||
-moz-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
-o-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
}
|
||||
.blueimp-gallery-single > .prev,
|
||||
.blueimp-gallery-left > .prev,
|
||||
.blueimp-gallery-single > .next,
|
||||
.blueimp-gallery-right > .next,
|
||||
.blueimp-gallery-single > .play-pause {
|
||||
display: none;
|
||||
}
|
||||
.blueimp-gallery > .slides > .slide > .slide-content,
|
||||
.blueimp-gallery > .prev,
|
||||
.blueimp-gallery > .next,
|
||||
.blueimp-gallery > .close,
|
||||
.blueimp-gallery > .play-pause {
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Replace PNGs with SVGs for capable browsers (excluding IE<9) */
|
||||
body:last-child .blueimp-gallery > .slides > .slide-error {
|
||||
background-image: url(../img/error.svg);
|
||||
}
|
||||
body:last-child .blueimp-gallery > .play-pause {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-size: 40px 20px;
|
||||
background-image: url(../img/play-pause.svg);
|
||||
}
|
||||
body:last-child .blueimp-gallery-playing > .play-pause {
|
||||
background-position: -20px 0;
|
||||
}
|
||||
|
||||
/* IE7 fixes */
|
||||
*+html .blueimp-gallery > .slides > .slide {
|
||||
min-height: 300px;
|
||||
}
|
||||
*+html .blueimp-gallery > .slides > .slide > .slide-content {
|
||||
position: relative;
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="64" height="64">
|
||||
<circle cx="32" cy="32" r="25" stroke="red" stroke-width="7" fill="black" fill-opacity="0.2"/>
|
||||
<rect x="28" y="7" width="8" height="50" fill="red" transform="rotate(45, 32, 32)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 306 B |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 606 B |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="30" height="15">
|
||||
<polygon points="2,1 2,14 13,7" stroke="black" stroke-width="1" fill="white"/>
|
||||
<rect x="17" y="2" width="4" height="11" stroke="black" stroke-width="1" fill="white"/>
|
||||
<rect x="24" y="2" width="4" height="11" stroke="black" stroke-width="1" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 382 B |
|
After Width: | Height: | Size: 2.7 KiB |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="64" height="64">
|
||||
<circle cx="32" cy="32" r="25" stroke="white" stroke-width="7" fill="black" fill-opacity="0.2"/>
|
||||
<polygon points="26,22 26,42 43,32" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 274 B |
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* blueimp Gallery Fullscreen JS 1.2.0
|
||||
* https://github.com/blueimp/Gallery
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* global define, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'./blueimp-helper',
|
||||
'./blueimp-gallery'
|
||||
], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.blueimp.helper || window.jQuery,
|
||||
window.blueimp.Gallery
|
||||
);
|
||||
}
|
||||
}(function ($, Gallery) {
|
||||
'use strict';
|
||||
|
||||
$.extend(Gallery.prototype.options, {
|
||||
// Defines if the gallery should open in fullscreen mode:
|
||||
fullScreen: false
|
||||
});
|
||||
|
||||
var initialize = Gallery.prototype.initialize,
|
||||
close = Gallery.prototype.close;
|
||||
|
||||
$.extend(Gallery.prototype, {
|
||||
|
||||
getFullScreenElement: function () {
|
||||
return document.fullscreenElement ||
|
||||
document.webkitFullscreenElement ||
|
||||
document.mozFullScreenElement ||
|
||||
document.msFullscreenElement;
|
||||
},
|
||||
|
||||
requestFullScreen: function (element) {
|
||||
if (element.requestFullscreen) {
|
||||
element.requestFullscreen();
|
||||
} else if (element.webkitRequestFullscreen) {
|
||||
element.webkitRequestFullscreen();
|
||||
} else if (element.mozRequestFullScreen) {
|
||||
element.mozRequestFullScreen();
|
||||
} else if (element.msRequestFullscreen) {
|
||||
element.msRequestFullscreen();
|
||||
}
|
||||
},
|
||||
|
||||
exitFullScreen: function () {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.webkitCancelFullScreen) {
|
||||
document.webkitCancelFullScreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
initialize.call(this);
|
||||
if (this.options.fullScreen && !this.getFullScreenElement()) {
|
||||
this.requestFullScreen(this.container[0]);
|
||||
}
|
||||
},
|
||||
|
||||
close: function () {
|
||||
if (this.getFullScreenElement() === this.container[0]) {
|
||||
this.exitFullScreen();
|
||||
}
|
||||
close.call(this);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return Gallery;
|
||||
}));
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* blueimp Gallery Indicator JS 1.1.0
|
||||
* https://github.com/blueimp/Gallery
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* global define, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'./blueimp-helper',
|
||||
'./blueimp-gallery'
|
||||
], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.blueimp.helper || window.jQuery,
|
||||
window.blueimp.Gallery
|
||||
);
|
||||
}
|
||||
}(function ($, Gallery) {
|
||||
'use strict';
|
||||
|
||||
$.extend(Gallery.prototype.options, {
|
||||
// The tag name, Id, element or querySelector of the indicator container:
|
||||
indicatorContainer: 'ol',
|
||||
// The class for the active indicator:
|
||||
activeIndicatorClass: 'active',
|
||||
// The list object property (or data attribute) with the thumbnail URL,
|
||||
// used as alternative to a thumbnail child element:
|
||||
thumbnailProperty: 'thumbnail',
|
||||
// Defines if the gallery indicators should display a thumbnail:
|
||||
thumbnailIndicators: true
|
||||
});
|
||||
|
||||
var initSlides = Gallery.prototype.initSlides,
|
||||
addSlide = Gallery.prototype.addSlide,
|
||||
resetSlides = Gallery.prototype.resetSlides,
|
||||
handleClick = Gallery.prototype.handleClick,
|
||||
handleSlide = Gallery.prototype.handleSlide,
|
||||
handleClose = Gallery.prototype.handleClose;
|
||||
|
||||
$.extend(Gallery.prototype, {
|
||||
|
||||
createIndicator: function (obj) {
|
||||
var indicator = this.indicatorPrototype.cloneNode(false),
|
||||
title = this.getItemProperty(obj, this.options.titleProperty),
|
||||
thumbnailProperty = this.options.thumbnailProperty,
|
||||
thumbnailUrl,
|
||||
thumbnail;
|
||||
if (this.options.thumbnailIndicators) {
|
||||
thumbnail = obj.getElementsByTagName && $(obj).find('img')[0];
|
||||
if (thumbnail) {
|
||||
thumbnailUrl = thumbnail.src;
|
||||
} else if (thumbnailProperty) {
|
||||
thumbnailUrl = this.getItemProperty(obj, thumbnailProperty);
|
||||
}
|
||||
if (thumbnailUrl) {
|
||||
indicator.style.backgroundImage = 'url("' + thumbnailUrl + '")';
|
||||
}
|
||||
}
|
||||
if (title) {
|
||||
indicator.title = title;
|
||||
}
|
||||
return indicator;
|
||||
},
|
||||
|
||||
addIndicator: function (index) {
|
||||
if (this.indicatorContainer.length) {
|
||||
var indicator = this.createIndicator(this.list[index]);
|
||||
indicator.setAttribute('data-index', index);
|
||||
this.indicatorContainer[0].appendChild(indicator);
|
||||
this.indicators.push(indicator);
|
||||
}
|
||||
},
|
||||
|
||||
setActiveIndicator: function (index) {
|
||||
if (this.indicators) {
|
||||
if (this.activeIndicator) {
|
||||
this.activeIndicator
|
||||
.removeClass(this.options.activeIndicatorClass);
|
||||
}
|
||||
this.activeIndicator = $(this.indicators[index]);
|
||||
this.activeIndicator
|
||||
.addClass(this.options.activeIndicatorClass);
|
||||
}
|
||||
},
|
||||
|
||||
initSlides: function (reload) {
|
||||
if (!reload) {
|
||||
this.indicatorContainer = this.container.find(
|
||||
this.options.indicatorContainer
|
||||
);
|
||||
if (this.indicatorContainer.length) {
|
||||
this.indicatorPrototype = document.createElement('li');
|
||||
this.indicators = this.indicatorContainer[0].children;
|
||||
}
|
||||
}
|
||||
initSlides.call(this, reload);
|
||||
},
|
||||
|
||||
addSlide: function (index) {
|
||||
addSlide.call(this, index);
|
||||
this.addIndicator(index);
|
||||
},
|
||||
|
||||
resetSlides: function () {
|
||||
resetSlides.call(this);
|
||||
this.indicatorContainer.empty();
|
||||
this.indicators = [];
|
||||
},
|
||||
|
||||
handleClick: function (event) {
|
||||
var target = event.target || event.srcElement,
|
||||
parent = target.parentNode;
|
||||
if (parent === this.indicatorContainer[0]) {
|
||||
// Click on indicator element
|
||||
this.preventDefault(event);
|
||||
this.slide(this.getNodeIndex(target));
|
||||
} else if (parent.parentNode === this.indicatorContainer[0]) {
|
||||
// Click on indicator child element
|
||||
this.preventDefault(event);
|
||||
this.slide(this.getNodeIndex(parent));
|
||||
} else {
|
||||
return handleClick.call(this, event);
|
||||
}
|
||||
},
|
||||
|
||||
handleSlide: function (index) {
|
||||
handleSlide.call(this, index);
|
||||
this.setActiveIndicator(index);
|
||||
},
|
||||
|
||||
handleClose: function () {
|
||||
if (this.activeIndicator) {
|
||||
this.activeIndicator
|
||||
.removeClass(this.options.activeIndicatorClass);
|
||||
}
|
||||
handleClose.call(this);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return Gallery;
|
||||
}));
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* blueimp Gallery Video Factory JS 1.1.1
|
||||
* https://github.com/blueimp/Gallery
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* global define, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'./blueimp-helper',
|
||||
'./blueimp-gallery'
|
||||
], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.blueimp.helper || window.jQuery,
|
||||
window.blueimp.Gallery
|
||||
);
|
||||
}
|
||||
}(function ($, Gallery) {
|
||||
'use strict';
|
||||
|
||||
$.extend(Gallery.prototype.options, {
|
||||
// The class for video content elements:
|
||||
videoContentClass: 'video-content',
|
||||
// The class for video when it is loading:
|
||||
videoLoadingClass: 'video-loading',
|
||||
// The class for video when it is playing:
|
||||
videoPlayingClass: 'video-playing',
|
||||
// The list object property (or data attribute) for the video poster URL:
|
||||
videoPosterProperty: 'poster',
|
||||
// The list object property (or data attribute) for the video sources array:
|
||||
videoSourcesProperty: 'sources'
|
||||
});
|
||||
|
||||
var handleSlide = Gallery.prototype.handleSlide;
|
||||
|
||||
$.extend(Gallery.prototype, {
|
||||
|
||||
handleSlide: function (index) {
|
||||
handleSlide.call(this, index);
|
||||
if (this.playingVideo) {
|
||||
this.playingVideo.pause();
|
||||
}
|
||||
},
|
||||
|
||||
videoFactory: function (obj, callback, videoInterface) {
|
||||
var that = this,
|
||||
options = this.options,
|
||||
videoContainerNode = this.elementPrototype.cloneNode(false),
|
||||
videoContainer = $(videoContainerNode),
|
||||
errorArgs = [{
|
||||
type: 'error',
|
||||
target: videoContainerNode
|
||||
}],
|
||||
video = videoInterface || document.createElement('video'),
|
||||
url = this.getItemProperty(obj, options.urlProperty),
|
||||
type = this.getItemProperty(obj, options.typeProperty),
|
||||
title = this.getItemProperty(obj, options.titleProperty),
|
||||
posterUrl = this.getItemProperty(obj, options.videoPosterProperty),
|
||||
posterImage,
|
||||
sources = this.getItemProperty(
|
||||
obj,
|
||||
options.videoSourcesProperty
|
||||
),
|
||||
source,
|
||||
playMediaControl,
|
||||
isLoading,
|
||||
hasControls;
|
||||
videoContainer.addClass(options.videoContentClass);
|
||||
if (title) {
|
||||
videoContainerNode.title = title;
|
||||
}
|
||||
if (video.canPlayType) {
|
||||
if (url && type && video.canPlayType(type)) {
|
||||
video.src = url;
|
||||
} else {
|
||||
while (sources && sources.length) {
|
||||
source = sources.shift();
|
||||
url = this.getItemProperty(source, options.urlProperty);
|
||||
type = this.getItemProperty(source, options.typeProperty);
|
||||
if (url && type && video.canPlayType(type)) {
|
||||
video.src = url;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (posterUrl) {
|
||||
video.poster = posterUrl;
|
||||
posterImage = this.imagePrototype.cloneNode(false);
|
||||
$(posterImage).addClass(options.toggleClass);
|
||||
posterImage.src = posterUrl;
|
||||
posterImage.draggable = false;
|
||||
videoContainerNode.appendChild(posterImage);
|
||||
}
|
||||
playMediaControl = document.createElement('a');
|
||||
playMediaControl.setAttribute('target', '_blank');
|
||||
if (!videoInterface) {
|
||||
playMediaControl.setAttribute('download', title);
|
||||
}
|
||||
playMediaControl.href = url;
|
||||
if (video.src) {
|
||||
video.controls = true;
|
||||
(videoInterface || $(video))
|
||||
.on('error', function () {
|
||||
that.setTimeout(callback, errorArgs);
|
||||
})
|
||||
.on('pause', function () {
|
||||
isLoading = false;
|
||||
videoContainer
|
||||
.removeClass(that.options.videoLoadingClass)
|
||||
.removeClass(that.options.videoPlayingClass);
|
||||
if (hasControls) {
|
||||
that.container.addClass(that.options.controlsClass);
|
||||
}
|
||||
delete that.playingVideo;
|
||||
if (that.interval) {
|
||||
that.play();
|
||||
}
|
||||
})
|
||||
.on('playing', function () {
|
||||
isLoading = false;
|
||||
videoContainer
|
||||
.removeClass(that.options.videoLoadingClass)
|
||||
.addClass(that.options.videoPlayingClass);
|
||||
if (that.container.hasClass(that.options.controlsClass)) {
|
||||
hasControls = true;
|
||||
that.container.removeClass(that.options.controlsClass);
|
||||
} else {
|
||||
hasControls = false;
|
||||
}
|
||||
})
|
||||
.on('play', function () {
|
||||
window.clearTimeout(that.timeout);
|
||||
isLoading = true;
|
||||
videoContainer.addClass(that.options.videoLoadingClass);
|
||||
that.playingVideo = video;
|
||||
});
|
||||
$(playMediaControl).on('click', function (event) {
|
||||
that.preventDefault(event);
|
||||
if (isLoading) {
|
||||
video.pause();
|
||||
} else {
|
||||
video.play();
|
||||
}
|
||||
});
|
||||
videoContainerNode.appendChild(
|
||||
(videoInterface && videoInterface.element) || video
|
||||
);
|
||||
}
|
||||
videoContainerNode.appendChild(playMediaControl);
|
||||
this.setTimeout(callback, [{
|
||||
type: 'load',
|
||||
target: videoContainerNode
|
||||
}]);
|
||||
return videoContainerNode;
|
||||
}
|
||||
});
|
||||
|
||||
return Gallery;
|
||||
}));
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* blueimp Gallery Vimeo Video Factory JS 1.2.0
|
||||
* https://github.com/blueimp/Gallery
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* global define, window, document, location, $f */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'./blueimp-helper',
|
||||
'./blueimp-gallery-video'
|
||||
], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.blueimp.helper || window.jQuery,
|
||||
window.blueimp.Gallery
|
||||
);
|
||||
}
|
||||
}(function ($, Gallery) {
|
||||
'use strict';
|
||||
|
||||
if (!window.postMessage) {
|
||||
return Gallery;
|
||||
}
|
||||
|
||||
$.extend(Gallery.prototype.options, {
|
||||
// The list object property (or data attribute) with the Vimeo video id:
|
||||
vimeoVideoIdProperty: 'vimeo',
|
||||
// The URL for the Vimeo video player, can be extended with custom parameters:
|
||||
// https://developer.vimeo.com/player/embedding
|
||||
vimeoPlayerUrl: '//player.vimeo.com/video/VIDEO_ID?api=1&player_id=PLAYER_ID',
|
||||
// The prefix for the Vimeo video player ID:
|
||||
vimeoPlayerIdPrefix: 'vimeo-player-',
|
||||
// Require a click on the native Vimeo player for the initial playback:
|
||||
vimeoClickToPlay: true
|
||||
});
|
||||
|
||||
var textFactory = Gallery.prototype.textFactory || Gallery.prototype.imageFactory,
|
||||
VimeoPlayer = function (url, videoId, playerId, clickToPlay) {
|
||||
this.url = url;
|
||||
this.videoId = videoId;
|
||||
this.playerId = playerId;
|
||||
this.clickToPlay = clickToPlay;
|
||||
this.element = document.createElement('div');
|
||||
this.listeners = {};
|
||||
},
|
||||
counter = 0;
|
||||
|
||||
$.extend(VimeoPlayer.prototype, {
|
||||
|
||||
canPlayType: function () {
|
||||
return true;
|
||||
},
|
||||
|
||||
on: function (type, func) {
|
||||
this.listeners[type] = func;
|
||||
return this;
|
||||
},
|
||||
|
||||
loadAPI: function () {
|
||||
var that = this,
|
||||
apiUrl = '//' + (location.protocol === 'https' ? 'secure-' : '') +
|
||||
'a.vimeocdn.com/js/froogaloop2.min.js',
|
||||
scriptTags = document.getElementsByTagName('script'),
|
||||
i = scriptTags.length,
|
||||
scriptTag,
|
||||
called,
|
||||
callback = function () {
|
||||
if (!called && that.playOnReady) {
|
||||
that.play();
|
||||
}
|
||||
called = true;
|
||||
};
|
||||
while (i) {
|
||||
i -= 1;
|
||||
if (scriptTags[i].src === apiUrl) {
|
||||
scriptTag = scriptTags[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!scriptTag) {
|
||||
scriptTag = document.createElement('script');
|
||||
scriptTag.src = apiUrl;
|
||||
}
|
||||
$(scriptTag).on('load', callback);
|
||||
scriptTags[0].parentNode.insertBefore(scriptTag, scriptTags[0]);
|
||||
// Fix for cached scripts on IE 8:
|
||||
if (/loaded|complete/.test(scriptTag.readyState)) {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
|
||||
onReady: function () {
|
||||
var that = this;
|
||||
this.ready = true;
|
||||
this.player.addEvent('play', function () {
|
||||
that.hasPlayed = true;
|
||||
that.onPlaying();
|
||||
});
|
||||
this.player.addEvent('pause', function () {
|
||||
that.onPause();
|
||||
});
|
||||
this.player.addEvent('finish', function () {
|
||||
that.onPause();
|
||||
});
|
||||
if (this.playOnReady) {
|
||||
this.play();
|
||||
}
|
||||
},
|
||||
|
||||
onPlaying: function () {
|
||||
if (this.playStatus < 2) {
|
||||
this.listeners.playing();
|
||||
this.playStatus = 2;
|
||||
}
|
||||
},
|
||||
|
||||
onPause: function () {
|
||||
this.listeners.pause();
|
||||
delete this.playStatus;
|
||||
},
|
||||
|
||||
insertIframe: function () {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.src = this.url
|
||||
.replace('VIDEO_ID', this.videoId)
|
||||
.replace('PLAYER_ID', this.playerId);
|
||||
iframe.id = this.playerId;
|
||||
this.element.parentNode.replaceChild(iframe, this.element);
|
||||
this.element = iframe;
|
||||
},
|
||||
|
||||
play: function () {
|
||||
var that = this;
|
||||
if (!this.playStatus) {
|
||||
this.listeners.play();
|
||||
this.playStatus = 1;
|
||||
}
|
||||
if (this.ready) {
|
||||
if (!this.hasPlayed && (this.clickToPlay || (window.navigator &&
|
||||
/iP(hone|od|ad)/.test(window.navigator.platform)))) {
|
||||
// Manually trigger the playing callback if clickToPlay
|
||||
// is enabled and to workaround a limitation in iOS,
|
||||
// which requires synchronous user interaction to start
|
||||
// the video playback:
|
||||
this.onPlaying();
|
||||
} else {
|
||||
this.player.api('play');
|
||||
}
|
||||
} else {
|
||||
this.playOnReady = true;
|
||||
if (!window.$f) {
|
||||
this.loadAPI();
|
||||
} else if (!this.player) {
|
||||
this.insertIframe();
|
||||
this.player = $f(this.element);
|
||||
this.player.addEvent('ready', function () {
|
||||
that.onReady();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
pause: function () {
|
||||
if (this.ready) {
|
||||
this.player.api('pause');
|
||||
} else if (this.playStatus) {
|
||||
delete this.playOnReady;
|
||||
this.listeners.pause();
|
||||
delete this.playStatus;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$.extend(Gallery.prototype, {
|
||||
|
||||
VimeoPlayer: VimeoPlayer,
|
||||
|
||||
textFactory: function (obj, callback) {
|
||||
var options = this.options,
|
||||
videoId = this.getItemProperty(obj, options.vimeoVideoIdProperty);
|
||||
if (videoId) {
|
||||
if (this.getItemProperty(obj, options.urlProperty) === undefined) {
|
||||
obj[options.urlProperty] = '//vimeo.com/' + videoId;
|
||||
}
|
||||
counter += 1;
|
||||
return this.videoFactory(
|
||||
obj,
|
||||
callback,
|
||||
new VimeoPlayer(
|
||||
options.vimeoPlayerUrl,
|
||||
videoId,
|
||||
options.vimeoPlayerIdPrefix + counter,
|
||||
options.vimeoClickToPlay
|
||||
)
|
||||
);
|
||||
}
|
||||
return textFactory.call(this, obj, callback);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return Gallery;
|
||||
}));
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* blueimp Gallery YouTube Video Factory JS 1.2.0
|
||||
* https://github.com/blueimp/Gallery
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* global define, window, document, YT */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define([
|
||||
'./blueimp-helper',
|
||||
'./blueimp-gallery-video'
|
||||
], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(
|
||||
window.blueimp.helper || window.jQuery,
|
||||
window.blueimp.Gallery
|
||||
);
|
||||
}
|
||||
}(function ($, Gallery) {
|
||||
'use strict';
|
||||
|
||||
if (!window.postMessage) {
|
||||
return Gallery;
|
||||
}
|
||||
|
||||
$.extend(Gallery.prototype.options, {
|
||||
// The list object property (or data attribute) with the YouTube video id:
|
||||
youTubeVideoIdProperty: 'youtube',
|
||||
// Optional object with parameters passed to the YouTube video player:
|
||||
// https://developers.google.com/youtube/player_parameters
|
||||
youTubePlayerVars: {
|
||||
wmode: 'transparent'
|
||||
},
|
||||
// Require a click on the native YouTube player for the initial playback:
|
||||
youTubeClickToPlay: true
|
||||
});
|
||||
|
||||
var textFactory = Gallery.prototype.textFactory || Gallery.prototype.imageFactory,
|
||||
YouTubePlayer = function (videoId, playerVars, clickToPlay) {
|
||||
this.videoId = videoId;
|
||||
this.playerVars = playerVars;
|
||||
this.clickToPlay = clickToPlay;
|
||||
this.element = document.createElement('div');
|
||||
this.listeners = {};
|
||||
};
|
||||
|
||||
$.extend(YouTubePlayer.prototype, {
|
||||
|
||||
canPlayType: function () {
|
||||
return true;
|
||||
},
|
||||
|
||||
on: function (type, func) {
|
||||
this.listeners[type] = func;
|
||||
return this;
|
||||
},
|
||||
|
||||
loadAPI: function () {
|
||||
var that = this,
|
||||
onYouTubeIframeAPIReady = window.onYouTubeIframeAPIReady,
|
||||
apiUrl = '//www.youtube.com/iframe_api',
|
||||
scriptTags = document.getElementsByTagName('script'),
|
||||
i = scriptTags.length,
|
||||
scriptTag;
|
||||
window.onYouTubeIframeAPIReady = function () {
|
||||
if (onYouTubeIframeAPIReady) {
|
||||
onYouTubeIframeAPIReady.apply(this);
|
||||
}
|
||||
if (that.playOnReady) {
|
||||
that.play();
|
||||
}
|
||||
};
|
||||
while (i) {
|
||||
i -= 1;
|
||||
if (scriptTags[i].src === apiUrl) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
scriptTag = document.createElement('script');
|
||||
scriptTag.src = apiUrl;
|
||||
scriptTags[0].parentNode.insertBefore(scriptTag, scriptTags[0]);
|
||||
},
|
||||
|
||||
onReady: function () {
|
||||
this.ready = true;
|
||||
if (this.playOnReady) {
|
||||
this.play();
|
||||
}
|
||||
},
|
||||
|
||||
onPlaying: function () {
|
||||
if (this.playStatus < 2) {
|
||||
this.listeners.playing();
|
||||
this.playStatus = 2;
|
||||
}
|
||||
},
|
||||
|
||||
onPause: function () {
|
||||
Gallery.prototype.setTimeout.call(
|
||||
this,
|
||||
this.checkSeek,
|
||||
null,
|
||||
2000
|
||||
);
|
||||
},
|
||||
|
||||
checkSeek: function () {
|
||||
if (this.stateChange === YT.PlayerState.PAUSED ||
|
||||
this.stateChange === YT.PlayerState.ENDED) {
|
||||
// check if current state change is actually paused
|
||||
this.listeners.pause();
|
||||
delete this.playStatus;
|
||||
}
|
||||
},
|
||||
|
||||
onStateChange: function (event) {
|
||||
switch (event.data) {
|
||||
case YT.PlayerState.PLAYING:
|
||||
this.hasPlayed = true;
|
||||
this.onPlaying();
|
||||
break;
|
||||
case YT.PlayerState.PAUSED:
|
||||
case YT.PlayerState.ENDED:
|
||||
this.onPause();
|
||||
break;
|
||||
}
|
||||
// Save most recent state change to this.stateChange
|
||||
this.stateChange = event.data;
|
||||
},
|
||||
|
||||
onError: function (event) {
|
||||
this.listeners.error(event);
|
||||
},
|
||||
|
||||
play: function () {
|
||||
var that = this;
|
||||
if (!this.playStatus) {
|
||||
this.listeners.play();
|
||||
this.playStatus = 1;
|
||||
}
|
||||
if (this.ready) {
|
||||
if (!this.hasPlayed && (this.clickToPlay || (window.navigator &&
|
||||
/iP(hone|od|ad)/.test(window.navigator.platform)))) {
|
||||
// Manually trigger the playing callback if clickToPlay
|
||||
// is enabled and to workaround a limitation in iOS,
|
||||
// which requires synchronous user interaction to start
|
||||
// the video playback:
|
||||
this.onPlaying();
|
||||
} else {
|
||||
this.player.playVideo();
|
||||
}
|
||||
} else {
|
||||
this.playOnReady = true;
|
||||
if (!(window.YT && YT.Player)) {
|
||||
this.loadAPI();
|
||||
} else if (!this.player) {
|
||||
this.player = new YT.Player(this.element, {
|
||||
videoId: this.videoId,
|
||||
playerVars: this.playerVars,
|
||||
events: {
|
||||
onReady: function () {
|
||||
that.onReady();
|
||||
},
|
||||
onStateChange: function (event) {
|
||||
that.onStateChange(event);
|
||||
},
|
||||
onError: function (event) {
|
||||
that.onError(event);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
pause: function () {
|
||||
if (this.ready) {
|
||||
this.player.pauseVideo();
|
||||
} else if (this.playStatus) {
|
||||
delete this.playOnReady;
|
||||
this.listeners.pause();
|
||||
delete this.playStatus;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$.extend(Gallery.prototype, {
|
||||
|
||||
YouTubePlayer: YouTubePlayer,
|
||||
|
||||
textFactory: function (obj, callback) {
|
||||
var options = this.options,
|
||||
videoId = this.getItemProperty(obj, options.youTubeVideoIdProperty);
|
||||
if (videoId) {
|
||||
if (this.getItemProperty(obj, options.urlProperty) === undefined) {
|
||||
obj[options.urlProperty] = '//www.youtube.com/watch?v=' + videoId;
|
||||
}
|
||||
if (this.getItemProperty(obj, options.videoPosterProperty) === undefined) {
|
||||
obj[options.videoPosterProperty] = '//img.youtube.com/vi/' + videoId +
|
||||
'/maxresdefault.jpg';
|
||||
}
|
||||
return this.videoFactory(
|
||||
obj,
|
||||
callback,
|
||||
new YouTubePlayer(
|
||||
videoId,
|
||||
options.youTubePlayerVars,
|
||||
options.youTubeClickToPlay
|
||||
)
|
||||
);
|
||||
}
|
||||
return textFactory.call(this, obj, callback);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return Gallery;
|
||||
}));
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* blueimp helper JS 1.2.0
|
||||
* https://github.com/blueimp/Gallery
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* global define, window, document */
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function extend(obj1, obj2) {
|
||||
var prop;
|
||||
for (prop in obj2) {
|
||||
if (obj2.hasOwnProperty(prop)) {
|
||||
obj1[prop] = obj2[prop];
|
||||
}
|
||||
}
|
||||
return obj1;
|
||||
}
|
||||
|
||||
function Helper(query) {
|
||||
if (!this || this.find !== Helper.prototype.find) {
|
||||
// Called as function instead of as constructor,
|
||||
// so we simply return a new instance:
|
||||
return new Helper(query);
|
||||
}
|
||||
this.length = 0;
|
||||
if (query) {
|
||||
if (typeof query === 'string') {
|
||||
query = this.find(query);
|
||||
}
|
||||
if (query.nodeType || query === query.window) {
|
||||
// Single HTML element
|
||||
this.length = 1;
|
||||
this[0] = query;
|
||||
} else {
|
||||
// HTML element collection
|
||||
var i = query.length;
|
||||
this.length = i;
|
||||
while (i) {
|
||||
i -= 1;
|
||||
this[i] = query[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Helper.extend = extend;
|
||||
|
||||
Helper.contains = function (container, element) {
|
||||
do {
|
||||
element = element.parentNode;
|
||||
if (element === container) {
|
||||
return true;
|
||||
}
|
||||
} while (element);
|
||||
return false;
|
||||
};
|
||||
|
||||
Helper.parseJSON = function (string) {
|
||||
return window.JSON && JSON.parse(string);
|
||||
};
|
||||
|
||||
extend(Helper.prototype, {
|
||||
|
||||
find: function (query) {
|
||||
var container = this[0] || document;
|
||||
if (typeof query === 'string') {
|
||||
if (container.querySelectorAll) {
|
||||
query = container.querySelectorAll(query);
|
||||
} else if (query.charAt(0) === '#') {
|
||||
query = container.getElementById(query.slice(1));
|
||||
} else {
|
||||
query = container.getElementsByTagName(query);
|
||||
}
|
||||
}
|
||||
return new Helper(query);
|
||||
},
|
||||
|
||||
hasClass: function (className) {
|
||||
if (!this[0]) {
|
||||
return false;
|
||||
}
|
||||
return new RegExp('(^|\\s+)' + className +
|
||||
'(\\s+|$)').test(this[0].className);
|
||||
},
|
||||
|
||||
addClass: function (className) {
|
||||
var i = this.length,
|
||||
element;
|
||||
while (i) {
|
||||
i -= 1;
|
||||
element = this[i];
|
||||
if (!element.className) {
|
||||
element.className = className;
|
||||
return this;
|
||||
}
|
||||
if (this.hasClass(className)) {
|
||||
return this;
|
||||
}
|
||||
element.className += ' ' + className;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
removeClass: function (className) {
|
||||
var regexp = new RegExp('(^|\\s+)' + className + '(\\s+|$)'),
|
||||
i = this.length,
|
||||
element;
|
||||
while (i) {
|
||||
i -= 1;
|
||||
element = this[i];
|
||||
element.className = element.className.replace(regexp, ' ');
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
on: function (eventName, handler) {
|
||||
var eventNames = eventName.split(/\s+/),
|
||||
i,
|
||||
element;
|
||||
while (eventNames.length) {
|
||||
eventName = eventNames.shift();
|
||||
i = this.length;
|
||||
while (i) {
|
||||
i -= 1;
|
||||
element = this[i];
|
||||
if (element.addEventListener) {
|
||||
element.addEventListener(eventName, handler, false);
|
||||
} else if (element.attachEvent) {
|
||||
element.attachEvent('on' + eventName, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
off: function (eventName, handler) {
|
||||
var eventNames = eventName.split(/\s+/),
|
||||
i,
|
||||
element;
|
||||
while (eventNames.length) {
|
||||
eventName = eventNames.shift();
|
||||
i = this.length;
|
||||
while (i) {
|
||||
i -= 1;
|
||||
element = this[i];
|
||||
if (element.removeEventListener) {
|
||||
element.removeEventListener(eventName, handler, false);
|
||||
} else if (element.detachEvent) {
|
||||
element.detachEvent('on' + eventName, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
empty: function () {
|
||||
var i = this.length,
|
||||
element;
|
||||
while (i) {
|
||||
i -= 1;
|
||||
element = this[i];
|
||||
while (element.hasChildNodes()) {
|
||||
element.removeChild(element.lastChild);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
first: function () {
|
||||
return new Helper(this[0]);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(function () {
|
||||
return Helper;
|
||||
});
|
||||
} else {
|
||||
window.blueimp = window.blueimp || {};
|
||||
window.blueimp.helper = Helper;
|
||||
}
|
||||
}());
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* blueimp Gallery jQuery plugin 1.2.2
|
||||
* https://github.com/blueimp/Gallery
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* global define, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([
|
||||
'jquery',
|
||||
'./blueimp-gallery'
|
||||
], factory);
|
||||
} else {
|
||||
factory(
|
||||
window.jQuery,
|
||||
window.blueimp.Gallery
|
||||
);
|
||||
}
|
||||
}(function ($, Gallery) {
|
||||
'use strict';
|
||||
|
||||
// Global click handler to open links with data-gallery attribute
|
||||
// in the Gallery lightbox:
|
||||
$(document).on('click', '[data-gallery]', function (event) {
|
||||
// Get the container id from the data-gallery attribute:
|
||||
var id = $(this).data('gallery'),
|
||||
widget = $(id),
|
||||
container = (widget.length && widget) ||
|
||||
$(Gallery.prototype.options.container),
|
||||
callbacks = {
|
||||
onopen: function () {
|
||||
container
|
||||
.data('gallery', this)
|
||||
.trigger('open');
|
||||
},
|
||||
onopened: function () {
|
||||
container.trigger('opened');
|
||||
},
|
||||
onslide: function () {
|
||||
container.trigger('slide', arguments);
|
||||
},
|
||||
onslideend: function () {
|
||||
container.trigger('slideend', arguments);
|
||||
},
|
||||
onslidecomplete: function () {
|
||||
container.trigger('slidecomplete', arguments);
|
||||
},
|
||||
onclose: function () {
|
||||
container.trigger('close');
|
||||
},
|
||||
onclosed: function () {
|
||||
container
|
||||
.trigger('closed')
|
||||
.removeData('gallery');
|
||||
}
|
||||
},
|
||||
options = $.extend(
|
||||
// Retrieve custom options from data-attributes
|
||||
// on the Gallery widget:
|
||||
container.data(),
|
||||
{
|
||||
container: container[0],
|
||||
index: this,
|
||||
event: event
|
||||
},
|
||||
callbacks
|
||||
),
|
||||
// Select all links with the same data-gallery attribute:
|
||||
links = $('[data-gallery="' + id + '"]');
|
||||
if (options.filter) {
|
||||
links = links.filter(options.filter);
|
||||
}
|
||||
return new Gallery(links, options);
|
||||
});
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "blueimp-gallery",
|
||||
"version": "2.15.2",
|
||||
"title": "blueimp Gallery",
|
||||
"description": "blueimp Gallery is a touch-enabled, responsive and customizable image and video gallery, carousel and lightbox, optimized for both mobile and desktop web browsers. It features swipe, mouse and keyboard navigation, transition effects, slideshow functionality, fullscreen support and on-demand content loading and can be extended to display additional content types.",
|
||||
"keywords": [
|
||||
"image",
|
||||
"video",
|
||||
"gallery",
|
||||
"carousel",
|
||||
"lightbox",
|
||||
"mobile",
|
||||
"desktop",
|
||||
"touch",
|
||||
"responsive",
|
||||
"swipe",
|
||||
"mouse",
|
||||
"keyboard",
|
||||
"navigation",
|
||||
"transition",
|
||||
"effects",
|
||||
"slideshow",
|
||||
"fullscreen"
|
||||
],
|
||||
"homepage": "https://github.com/blueimp/Gallery",
|
||||
"author": {
|
||||
"name": "Sebastian Tschan",
|
||||
"url": "https://blueimp.net"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Sebastian Tschan",
|
||||
"url": "https://blueimp.net"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/blueimp/Gallery.git"
|
||||
},
|
||||
"bugs": "https://github.com/blueimp/Gallery/issues",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://www.opensource.org/licenses/MIT"
|
||||
}
|
||||
],
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.5",
|
||||
"grunt-contrib-less": "~0.11.3",
|
||||
"grunt-contrib-uglify": "~0.5.0",
|
||||
"grunt-contrib-jshint": "~0.10.0",
|
||||
"grunt-bump-build-git": "~1.1.1"
|
||||
}
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 329 B |
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
* JavaScript Load Image Exif Map 1.0.2
|
||||
* https://github.com/blueimp/JavaScript-Load-Image
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Exif tags mapping based on
|
||||
* https://github.com/jseidelin/exif-js
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/*global define, window */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['load-image', 'load-image-exif'], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(window.loadImage);
|
||||
}
|
||||
}(function (loadImage) {
|
||||
'use strict';
|
||||
|
||||
loadImage.ExifMap.prototype.tags = {
|
||||
// =================
|
||||
// TIFF tags (IFD0):
|
||||
// =================
|
||||
0x0100: 'ImageWidth',
|
||||
0x0101: 'ImageHeight',
|
||||
0x8769: 'ExifIFDPointer',
|
||||
0x8825: 'GPSInfoIFDPointer',
|
||||
0xA005: 'InteroperabilityIFDPointer',
|
||||
0x0102: 'BitsPerSample',
|
||||
0x0103: 'Compression',
|
||||
0x0106: 'PhotometricInterpretation',
|
||||
0x0112: 'Orientation',
|
||||
0x0115: 'SamplesPerPixel',
|
||||
0x011C: 'PlanarConfiguration',
|
||||
0x0212: 'YCbCrSubSampling',
|
||||
0x0213: 'YCbCrPositioning',
|
||||
0x011A: 'XResolution',
|
||||
0x011B: 'YResolution',
|
||||
0x0128: 'ResolutionUnit',
|
||||
0x0111: 'StripOffsets',
|
||||
0x0116: 'RowsPerStrip',
|
||||
0x0117: 'StripByteCounts',
|
||||
0x0201: 'JPEGInterchangeFormat',
|
||||
0x0202: 'JPEGInterchangeFormatLength',
|
||||
0x012D: 'TransferFunction',
|
||||
0x013E: 'WhitePoint',
|
||||
0x013F: 'PrimaryChromaticities',
|
||||
0x0211: 'YCbCrCoefficients',
|
||||
0x0214: 'ReferenceBlackWhite',
|
||||
0x0132: 'DateTime',
|
||||
0x010E: 'ImageDescription',
|
||||
0x010F: 'Make',
|
||||
0x0110: 'Model',
|
||||
0x0131: 'Software',
|
||||
0x013B: 'Artist',
|
||||
0x8298: 'Copyright',
|
||||
// ==================
|
||||
// Exif Sub IFD tags:
|
||||
// ==================
|
||||
0x9000: 'ExifVersion', // EXIF version
|
||||
0xA000: 'FlashpixVersion', // Flashpix format version
|
||||
0xA001: 'ColorSpace', // Color space information tag
|
||||
0xA002: 'PixelXDimension', // Valid width of meaningful image
|
||||
0xA003: 'PixelYDimension', // Valid height of meaningful image
|
||||
0xA500: 'Gamma',
|
||||
0x9101: 'ComponentsConfiguration', // Information about channels
|
||||
0x9102: 'CompressedBitsPerPixel', // Compressed bits per pixel
|
||||
0x927C: 'MakerNote', // Any desired information written by the manufacturer
|
||||
0x9286: 'UserComment', // Comments by user
|
||||
0xA004: 'RelatedSoundFile', // Name of related sound file
|
||||
0x9003: 'DateTimeOriginal', // Date and time when the original image was generated
|
||||
0x9004: 'DateTimeDigitized', // Date and time when the image was stored digitally
|
||||
0x9290: 'SubSecTime', // Fractions of seconds for DateTime
|
||||
0x9291: 'SubSecTimeOriginal', // Fractions of seconds for DateTimeOriginal
|
||||
0x9292: 'SubSecTimeDigitized', // Fractions of seconds for DateTimeDigitized
|
||||
0x829A: 'ExposureTime', // Exposure time (in seconds)
|
||||
0x829D: 'FNumber',
|
||||
0x8822: 'ExposureProgram', // Exposure program
|
||||
0x8824: 'SpectralSensitivity', // Spectral sensitivity
|
||||
0x8827: 'PhotographicSensitivity', // EXIF 2.3, ISOSpeedRatings in EXIF 2.2
|
||||
0x8828: 'OECF', // Optoelectric conversion factor
|
||||
0x8830: 'SensitivityType',
|
||||
0x8831: 'StandardOutputSensitivity',
|
||||
0x8832: 'RecommendedExposureIndex',
|
||||
0x8833: 'ISOSpeed',
|
||||
0x8834: 'ISOSpeedLatitudeyyy',
|
||||
0x8835: 'ISOSpeedLatitudezzz',
|
||||
0x9201: 'ShutterSpeedValue', // Shutter speed
|
||||
0x9202: 'ApertureValue', // Lens aperture
|
||||
0x9203: 'BrightnessValue', // Value of brightness
|
||||
0x9204: 'ExposureBias', // Exposure bias
|
||||
0x9205: 'MaxApertureValue', // Smallest F number of lens
|
||||
0x9206: 'SubjectDistance', // Distance to subject in meters
|
||||
0x9207: 'MeteringMode', // Metering mode
|
||||
0x9208: 'LightSource', // Kind of light source
|
||||
0x9209: 'Flash', // Flash status
|
||||
0x9214: 'SubjectArea', // Location and area of main subject
|
||||
0x920A: 'FocalLength', // Focal length of the lens in mm
|
||||
0xA20B: 'FlashEnergy', // Strobe energy in BCPS
|
||||
0xA20C: 'SpatialFrequencyResponse',
|
||||
0xA20E: 'FocalPlaneXResolution', // Number of pixels in width direction per FPRUnit
|
||||
0xA20F: 'FocalPlaneYResolution', // Number of pixels in height direction per FPRUnit
|
||||
0xA210: 'FocalPlaneResolutionUnit', // Unit for measuring the focal plane resolution
|
||||
0xA214: 'SubjectLocation', // Location of subject in image
|
||||
0xA215: 'ExposureIndex', // Exposure index selected on camera
|
||||
0xA217: 'SensingMethod', // Image sensor type
|
||||
0xA300: 'FileSource', // Image source (3 == DSC)
|
||||
0xA301: 'SceneType', // Scene type (1 == directly photographed)
|
||||
0xA302: 'CFAPattern', // Color filter array geometric pattern
|
||||
0xA401: 'CustomRendered', // Special processing
|
||||
0xA402: 'ExposureMode', // Exposure mode
|
||||
0xA403: 'WhiteBalance', // 1 = auto white balance, 2 = manual
|
||||
0xA404: 'DigitalZoomRatio', // Digital zoom ratio
|
||||
0xA405: 'FocalLengthIn35mmFilm',
|
||||
0xA406: 'SceneCaptureType', // Type of scene
|
||||
0xA407: 'GainControl', // Degree of overall image gain adjustment
|
||||
0xA408: 'Contrast', // Direction of contrast processing applied by camera
|
||||
0xA409: 'Saturation', // Direction of saturation processing applied by camera
|
||||
0xA40A: 'Sharpness', // Direction of sharpness processing applied by camera
|
||||
0xA40B: 'DeviceSettingDescription',
|
||||
0xA40C: 'SubjectDistanceRange', // Distance to subject
|
||||
0xA420: 'ImageUniqueID', // Identifier assigned uniquely to each image
|
||||
0xA430: 'CameraOwnerName',
|
||||
0xA431: 'BodySerialNumber',
|
||||
0xA432: 'LensSpecification',
|
||||
0xA433: 'LensMake',
|
||||
0xA434: 'LensModel',
|
||||
0xA435: 'LensSerialNumber',
|
||||
// ==============
|
||||
// GPS Info tags:
|
||||
// ==============
|
||||
0x0000: 'GPSVersionID',
|
||||
0x0001: 'GPSLatitudeRef',
|
||||
0x0002: 'GPSLatitude',
|
||||
0x0003: 'GPSLongitudeRef',
|
||||
0x0004: 'GPSLongitude',
|
||||
0x0005: 'GPSAltitudeRef',
|
||||
0x0006: 'GPSAltitude',
|
||||
0x0007: 'GPSTimeStamp',
|
||||
0x0008: 'GPSSatellites',
|
||||
0x0009: 'GPSStatus',
|
||||
0x000A: 'GPSMeasureMode',
|
||||
0x000B: 'GPSDOP',
|
||||
0x000C: 'GPSSpeedRef',
|
||||
0x000D: 'GPSSpeed',
|
||||
0x000E: 'GPSTrackRef',
|
||||
0x000F: 'GPSTrack',
|
||||
0x0010: 'GPSImgDirectionRef',
|
||||
0x0011: 'GPSImgDirection',
|
||||
0x0012: 'GPSMapDatum',
|
||||
0x0013: 'GPSDestLatitudeRef',
|
||||
0x0014: 'GPSDestLatitude',
|
||||
0x0015: 'GPSDestLongitudeRef',
|
||||
0x0016: 'GPSDestLongitude',
|
||||
0x0017: 'GPSDestBearingRef',
|
||||
0x0018: 'GPSDestBearing',
|
||||
0x0019: 'GPSDestDistanceRef',
|
||||
0x001A: 'GPSDestDistance',
|
||||
0x001B: 'GPSProcessingMethod',
|
||||
0x001C: 'GPSAreaInformation',
|
||||
0x001D: 'GPSDateStamp',
|
||||
0x001E: 'GPSDifferential',
|
||||
0x001F: 'GPSHPositioningError'
|
||||
};
|
||||
|
||||
loadImage.ExifMap.prototype.stringValues = {
|
||||
ExposureProgram: {
|
||||
0: 'Undefined',
|
||||
1: 'Manual',
|
||||
2: 'Normal program',
|
||||
3: 'Aperture priority',
|
||||
4: 'Shutter priority',
|
||||
5: 'Creative program',
|
||||
6: 'Action program',
|
||||
7: 'Portrait mode',
|
||||
8: 'Landscape mode'
|
||||
},
|
||||
MeteringMode: {
|
||||
0: 'Unknown',
|
||||
1: 'Average',
|
||||
2: 'CenterWeightedAverage',
|
||||
3: 'Spot',
|
||||
4: 'MultiSpot',
|
||||
5: 'Pattern',
|
||||
6: 'Partial',
|
||||
255: 'Other'
|
||||
},
|
||||
LightSource: {
|
||||
0: 'Unknown',
|
||||
1: 'Daylight',
|
||||
2: 'Fluorescent',
|
||||
3: 'Tungsten (incandescent light)',
|
||||
4: 'Flash',
|
||||
9: 'Fine weather',
|
||||
10: 'Cloudy weather',
|
||||
11: 'Shade',
|
||||
12: 'Daylight fluorescent (D 5700 - 7100K)',
|
||||
13: 'Day white fluorescent (N 4600 - 5400K)',
|
||||
14: 'Cool white fluorescent (W 3900 - 4500K)',
|
||||
15: 'White fluorescent (WW 3200 - 3700K)',
|
||||
17: 'Standard light A',
|
||||
18: 'Standard light B',
|
||||
19: 'Standard light C',
|
||||
20: 'D55',
|
||||
21: 'D65',
|
||||
22: 'D75',
|
||||
23: 'D50',
|
||||
24: 'ISO studio tungsten',
|
||||
255: 'Other'
|
||||
},
|
||||
Flash: {
|
||||
0x0000: 'Flash did not fire',
|
||||
0x0001: 'Flash fired',
|
||||
0x0005: 'Strobe return light not detected',
|
||||
0x0007: 'Strobe return light detected',
|
||||
0x0009: 'Flash fired, compulsory flash mode',
|
||||
0x000D: 'Flash fired, compulsory flash mode, return light not detected',
|
||||
0x000F: 'Flash fired, compulsory flash mode, return light detected',
|
||||
0x0010: 'Flash did not fire, compulsory flash mode',
|
||||
0x0018: 'Flash did not fire, auto mode',
|
||||
0x0019: 'Flash fired, auto mode',
|
||||
0x001D: 'Flash fired, auto mode, return light not detected',
|
||||
0x001F: 'Flash fired, auto mode, return light detected',
|
||||
0x0020: 'No flash function',
|
||||
0x0041: 'Flash fired, red-eye reduction mode',
|
||||
0x0045: 'Flash fired, red-eye reduction mode, return light not detected',
|
||||
0x0047: 'Flash fired, red-eye reduction mode, return light detected',
|
||||
0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode',
|
||||
0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
|
||||
0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
|
||||
0x0059: 'Flash fired, auto mode, red-eye reduction mode',
|
||||
0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
|
||||
0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode'
|
||||
},
|
||||
SensingMethod: {
|
||||
1: 'Undefined',
|
||||
2: 'One-chip color area sensor',
|
||||
3: 'Two-chip color area sensor',
|
||||
4: 'Three-chip color area sensor',
|
||||
5: 'Color sequential area sensor',
|
||||
7: 'Trilinear sensor',
|
||||
8: 'Color sequential linear sensor'
|
||||
},
|
||||
SceneCaptureType: {
|
||||
0: 'Standard',
|
||||
1: 'Landscape',
|
||||
2: 'Portrait',
|
||||
3: 'Night scene'
|
||||
},
|
||||
SceneType: {
|
||||
1: 'Directly photographed'
|
||||
},
|
||||
CustomRendered: {
|
||||
0: 'Normal process',
|
||||
1: 'Custom process'
|
||||
},
|
||||
WhiteBalance: {
|
||||
0: 'Auto white balance',
|
||||
1: 'Manual white balance'
|
||||
},
|
||||
GainControl: {
|
||||
0: 'None',
|
||||
1: 'Low gain up',
|
||||
2: 'High gain up',
|
||||
3: 'Low gain down',
|
||||
4: 'High gain down'
|
||||
},
|
||||
Contrast: {
|
||||
0: 'Normal',
|
||||
1: 'Soft',
|
||||
2: 'Hard'
|
||||
},
|
||||
Saturation: {
|
||||
0: 'Normal',
|
||||
1: 'Low saturation',
|
||||
2: 'High saturation'
|
||||
},
|
||||
Sharpness: {
|
||||
0: 'Normal',
|
||||
1: 'Soft',
|
||||
2: 'Hard'
|
||||
},
|
||||
SubjectDistanceRange: {
|
||||
0: 'Unknown',
|
||||
1: 'Macro',
|
||||
2: 'Close view',
|
||||
3: 'Distant view'
|
||||
},
|
||||
FileSource: {
|
||||
3: 'DSC'
|
||||
},
|
||||
ComponentsConfiguration: {
|
||||
0: '',
|
||||
1: 'Y',
|
||||
2: 'Cb',
|
||||
3: 'Cr',
|
||||
4: 'R',
|
||||
5: 'G',
|
||||
6: 'B'
|
||||
},
|
||||
Orientation: {
|
||||
1: 'top-left',
|
||||
2: 'top-right',
|
||||
3: 'bottom-right',
|
||||
4: 'bottom-left',
|
||||
5: 'left-top',
|
||||
6: 'right-top',
|
||||
7: 'right-bottom',
|
||||
8: 'left-bottom'
|
||||
}
|
||||
};
|
||||
|
||||
loadImage.ExifMap.prototype.getText = function (id) {
|
||||
var value = this.get(id);
|
||||
switch (id) {
|
||||
case 'LightSource':
|
||||
case 'Flash':
|
||||
case 'MeteringMode':
|
||||
case 'ExposureProgram':
|
||||
case 'SensingMethod':
|
||||
case 'SceneCaptureType':
|
||||
case 'SceneType':
|
||||
case 'CustomRendered':
|
||||
case 'WhiteBalance':
|
||||
case 'GainControl':
|
||||
case 'Contrast':
|
||||
case 'Saturation':
|
||||
case 'Sharpness':
|
||||
case 'SubjectDistanceRange':
|
||||
case 'FileSource':
|
||||
case 'Orientation':
|
||||
return this.stringValues[id][value];
|
||||
case 'ExifVersion':
|
||||
case 'FlashpixVersion':
|
||||
return String.fromCharCode(value[0], value[1], value[2], value[3]);
|
||||
case 'ComponentsConfiguration':
|
||||
return this.stringValues[id][value[0]] +
|
||||
this.stringValues[id][value[1]] +
|
||||
this.stringValues[id][value[2]] +
|
||||
this.stringValues[id][value[3]];
|
||||
case 'GPSVersionID':
|
||||
return value[0] + '.' + value[1] + '.' + value[2] + '.' + value[3];
|
||||
}
|
||||
return String(value);
|
||||
};
|
||||
|
||||
(function (exifMapPrototype) {
|
||||
var tags = exifMapPrototype.tags,
|
||||
map = exifMapPrototype.map,
|
||||
prop;
|
||||
|
||||
// Map the tag names to tags:
|
||||
for (prop in tags) {
|
||||
if (tags.hasOwnProperty(prop)) {
|
||||
map[tags[prop]] = prop;
|
||||
}
|
||||
}
|
||||
}(loadImage.ExifMap.prototype));
|
||||
|
||||
loadImage.ExifMap.prototype.getAll = function () {
|
||||
var map = {},
|
||||
prop,
|
||||
id;
|
||||
for (prop in this) {
|
||||
if (this.hasOwnProperty(prop)) {
|
||||
id = this.tags[prop];
|
||||
if (id) {
|
||||
map[id] = this.getText(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
};
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* JavaScript Load Image Exif Parser 1.0.0
|
||||
* https://github.com/blueimp/JavaScript-Load-Image
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/*jslint unparam: true */
|
||||
/*global define, window, console */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['load-image', 'load-image-meta'], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(window.loadImage);
|
||||
}
|
||||
}(function (loadImage) {
|
||||
'use strict';
|
||||
|
||||
loadImage.ExifMap = function () {
|
||||
return this;
|
||||
};
|
||||
|
||||
loadImage.ExifMap.prototype.map = {
|
||||
'Orientation': 0x0112
|
||||
};
|
||||
|
||||
loadImage.ExifMap.prototype.get = function (id) {
|
||||
return this[id] || this[this.map[id]];
|
||||
};
|
||||
|
||||
loadImage.getExifThumbnail = function (dataView, offset, length) {
|
||||
var hexData,
|
||||
i,
|
||||
b;
|
||||
if (!length || offset + length > dataView.byteLength) {
|
||||
console.log('Invalid Exif data: Invalid thumbnail data.');
|
||||
return;
|
||||
}
|
||||
hexData = [];
|
||||
for (i = 0; i < length; i += 1) {
|
||||
b = dataView.getUint8(offset + i);
|
||||
hexData.push((b < 16 ? '0' : '') + b.toString(16));
|
||||
}
|
||||
return 'data:image/jpeg,%' + hexData.join('%');
|
||||
};
|
||||
|
||||
loadImage.exifTagTypes = {
|
||||
// byte, 8-bit unsigned int:
|
||||
1: {
|
||||
getValue: function (dataView, dataOffset) {
|
||||
return dataView.getUint8(dataOffset);
|
||||
},
|
||||
size: 1
|
||||
},
|
||||
// ascii, 8-bit byte:
|
||||
2: {
|
||||
getValue: function (dataView, dataOffset) {
|
||||
return String.fromCharCode(dataView.getUint8(dataOffset));
|
||||
},
|
||||
size: 1,
|
||||
ascii: true
|
||||
},
|
||||
// short, 16 bit int:
|
||||
3: {
|
||||
getValue: function (dataView, dataOffset, littleEndian) {
|
||||
return dataView.getUint16(dataOffset, littleEndian);
|
||||
},
|
||||
size: 2
|
||||
},
|
||||
// long, 32 bit int:
|
||||
4: {
|
||||
getValue: function (dataView, dataOffset, littleEndian) {
|
||||
return dataView.getUint32(dataOffset, littleEndian);
|
||||
},
|
||||
size: 4
|
||||
},
|
||||
// rational = two long values, first is numerator, second is denominator:
|
||||
5: {
|
||||
getValue: function (dataView, dataOffset, littleEndian) {
|
||||
return dataView.getUint32(dataOffset, littleEndian) /
|
||||
dataView.getUint32(dataOffset + 4, littleEndian);
|
||||
},
|
||||
size: 8
|
||||
},
|
||||
// slong, 32 bit signed int:
|
||||
9: {
|
||||
getValue: function (dataView, dataOffset, littleEndian) {
|
||||
return dataView.getInt32(dataOffset, littleEndian);
|
||||
},
|
||||
size: 4
|
||||
},
|
||||
// srational, two slongs, first is numerator, second is denominator:
|
||||
10: {
|
||||
getValue: function (dataView, dataOffset, littleEndian) {
|
||||
return dataView.getInt32(dataOffset, littleEndian) /
|
||||
dataView.getInt32(dataOffset + 4, littleEndian);
|
||||
},
|
||||
size: 8
|
||||
}
|
||||
};
|
||||
// undefined, 8-bit byte, value depending on field:
|
||||
loadImage.exifTagTypes[7] = loadImage.exifTagTypes[1];
|
||||
|
||||
loadImage.getExifValue = function (dataView, tiffOffset, offset, type, length, littleEndian) {
|
||||
var tagType = loadImage.exifTagTypes[type],
|
||||
tagSize,
|
||||
dataOffset,
|
||||
values,
|
||||
i,
|
||||
str,
|
||||
c;
|
||||
if (!tagType) {
|
||||
console.log('Invalid Exif data: Invalid tag type.');
|
||||
return;
|
||||
}
|
||||
tagSize = tagType.size * length;
|
||||
// Determine if the value is contained in the dataOffset bytes,
|
||||
// or if the value at the dataOffset is a pointer to the actual data:
|
||||
dataOffset = tagSize > 4 ?
|
||||
tiffOffset + dataView.getUint32(offset + 8, littleEndian) : (offset + 8);
|
||||
if (dataOffset + tagSize > dataView.byteLength) {
|
||||
console.log('Invalid Exif data: Invalid data offset.');
|
||||
return;
|
||||
}
|
||||
if (length === 1) {
|
||||
return tagType.getValue(dataView, dataOffset, littleEndian);
|
||||
}
|
||||
values = [];
|
||||
for (i = 0; i < length; i += 1) {
|
||||
values[i] = tagType.getValue(dataView, dataOffset + i * tagType.size, littleEndian);
|
||||
}
|
||||
if (tagType.ascii) {
|
||||
str = '';
|
||||
// Concatenate the chars:
|
||||
for (i = 0; i < values.length; i += 1) {
|
||||
c = values[i];
|
||||
// Ignore the terminating NULL byte(s):
|
||||
if (c === '\u0000') {
|
||||
break;
|
||||
}
|
||||
str += c;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
return values;
|
||||
};
|
||||
|
||||
loadImage.parseExifTag = function (dataView, tiffOffset, offset, littleEndian, data) {
|
||||
var tag = dataView.getUint16(offset, littleEndian);
|
||||
data.exif[tag] = loadImage.getExifValue(
|
||||
dataView,
|
||||
tiffOffset,
|
||||
offset,
|
||||
dataView.getUint16(offset + 2, littleEndian), // tag type
|
||||
dataView.getUint32(offset + 4, littleEndian), // tag length
|
||||
littleEndian
|
||||
);
|
||||
};
|
||||
|
||||
loadImage.parseExifTags = function (dataView, tiffOffset, dirOffset, littleEndian, data) {
|
||||
var tagsNumber,
|
||||
dirEndOffset,
|
||||
i;
|
||||
if (dirOffset + 6 > dataView.byteLength) {
|
||||
console.log('Invalid Exif data: Invalid directory offset.');
|
||||
return;
|
||||
}
|
||||
tagsNumber = dataView.getUint16(dirOffset, littleEndian);
|
||||
dirEndOffset = dirOffset + 2 + 12 * tagsNumber;
|
||||
if (dirEndOffset + 4 > dataView.byteLength) {
|
||||
console.log('Invalid Exif data: Invalid directory size.');
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < tagsNumber; i += 1) {
|
||||
this.parseExifTag(
|
||||
dataView,
|
||||
tiffOffset,
|
||||
dirOffset + 2 + 12 * i, // tag offset
|
||||
littleEndian,
|
||||
data
|
||||
);
|
||||
}
|
||||
// Return the offset to the next directory:
|
||||
return dataView.getUint32(dirEndOffset, littleEndian);
|
||||
};
|
||||
|
||||
loadImage.parseExifData = function (dataView, offset, length, data, options) {
|
||||
if (options.disableExif) {
|
||||
return;
|
||||
}
|
||||
var tiffOffset = offset + 10,
|
||||
littleEndian,
|
||||
dirOffset,
|
||||
thumbnailData;
|
||||
// Check for the ASCII code for "Exif" (0x45786966):
|
||||
if (dataView.getUint32(offset + 4) !== 0x45786966) {
|
||||
// No Exif data, might be XMP data instead
|
||||
return;
|
||||
}
|
||||
if (tiffOffset + 8 > dataView.byteLength) {
|
||||
console.log('Invalid Exif data: Invalid segment size.');
|
||||
return;
|
||||
}
|
||||
// Check for the two null bytes:
|
||||
if (dataView.getUint16(offset + 8) !== 0x0000) {
|
||||
console.log('Invalid Exif data: Missing byte alignment offset.');
|
||||
return;
|
||||
}
|
||||
// Check the byte alignment:
|
||||
switch (dataView.getUint16(tiffOffset)) {
|
||||
case 0x4949:
|
||||
littleEndian = true;
|
||||
break;
|
||||
case 0x4D4D:
|
||||
littleEndian = false;
|
||||
break;
|
||||
default:
|
||||
console.log('Invalid Exif data: Invalid byte alignment marker.');
|
||||
return;
|
||||
}
|
||||
// Check for the TIFF tag marker (0x002A):
|
||||
if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002A) {
|
||||
console.log('Invalid Exif data: Missing TIFF marker.');
|
||||
return;
|
||||
}
|
||||
// Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:
|
||||
dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
|
||||
// Create the exif object to store the tags:
|
||||
data.exif = new loadImage.ExifMap();
|
||||
// Parse the tags of the main image directory and retrieve the
|
||||
// offset to the next directory, usually the thumbnail directory:
|
||||
dirOffset = loadImage.parseExifTags(
|
||||
dataView,
|
||||
tiffOffset,
|
||||
tiffOffset + dirOffset,
|
||||
littleEndian,
|
||||
data
|
||||
);
|
||||
if (dirOffset && !options.disableExifThumbnail) {
|
||||
thumbnailData = {exif: {}};
|
||||
dirOffset = loadImage.parseExifTags(
|
||||
dataView,
|
||||
tiffOffset,
|
||||
tiffOffset + dirOffset,
|
||||
littleEndian,
|
||||
thumbnailData
|
||||
);
|
||||
// Check for JPEG Thumbnail offset:
|
||||
if (thumbnailData.exif[0x0201]) {
|
||||
data.exif.Thumbnail = loadImage.getExifThumbnail(
|
||||
dataView,
|
||||
tiffOffset + thumbnailData.exif[0x0201],
|
||||
thumbnailData.exif[0x0202] // Thumbnail data length
|
||||
);
|
||||
}
|
||||
}
|
||||
// Check for Exif Sub IFD Pointer:
|
||||
if (data.exif[0x8769] && !options.disableExifSub) {
|
||||
loadImage.parseExifTags(
|
||||
dataView,
|
||||
tiffOffset,
|
||||
tiffOffset + data.exif[0x8769], // directory offset
|
||||
littleEndian,
|
||||
data
|
||||
);
|
||||
}
|
||||
// Check for GPS Info IFD Pointer:
|
||||
if (data.exif[0x8825] && !options.disableExifGps) {
|
||||
loadImage.parseExifTags(
|
||||
dataView,
|
||||
tiffOffset,
|
||||
tiffOffset + data.exif[0x8825], // directory offset
|
||||
littleEndian,
|
||||
data
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Registers the Exif parser for the APP1 JPEG meta data segment:
|
||||
loadImage.metaDataParsers.jpeg[0xffe1].push(loadImage.parseExifData);
|
||||
|
||||
// Adds the following properties to the parseMetaData callback data:
|
||||
// * exif: The exif tags, parsed by the parseExifData method
|
||||
|
||||
// Adds the following options to the parseMetaData method:
|
||||
// * disableExif: Disables Exif parsing.
|
||||
// * disableExifThumbnail: Disables parsing of the Exif Thumbnail.
|
||||
// * disableExifSub: Disables parsing of the Exif Sub IFD.
|
||||
// * disableExifGps: Disables parsing of the Exif GPS Info IFD.
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* JavaScript Load Image iOS scaling fixes 1.0.3
|
||||
* https://github.com/blueimp/JavaScript-Load-Image
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* iOS image scaling fixes based on
|
||||
* https://github.com/stomita/ios-imagefile-megapixel
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/*jslint nomen: true, bitwise: true */
|
||||
/*global define, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['load-image'], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(window.loadImage);
|
||||
}
|
||||
}(function (loadImage) {
|
||||
'use strict';
|
||||
|
||||
// Only apply fixes on the iOS platform:
|
||||
if (!window.navigator || !window.navigator.platform ||
|
||||
!(/iP(hone|od|ad)/).test(window.navigator.platform)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var originalRenderMethod = loadImage.renderImageToCanvas;
|
||||
|
||||
// Detects subsampling in JPEG images:
|
||||
loadImage.detectSubsampling = function (img) {
|
||||
var canvas,
|
||||
context;
|
||||
if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images
|
||||
canvas = document.createElement('canvas');
|
||||
canvas.width = canvas.height = 1;
|
||||
context = canvas.getContext('2d');
|
||||
context.drawImage(img, -img.width + 1, 0);
|
||||
// subsampled image becomes half smaller in rendering size.
|
||||
// check alpha channel value to confirm image is covering edge pixel or not.
|
||||
// if alpha value is 0 image is not covering, hence subsampled.
|
||||
return context.getImageData(0, 0, 1, 1).data[3] === 0;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Detects vertical squash in JPEG images:
|
||||
loadImage.detectVerticalSquash = function (img, subsampled) {
|
||||
var naturalHeight = img.naturalHeight || img.height,
|
||||
canvas = document.createElement('canvas'),
|
||||
context = canvas.getContext('2d'),
|
||||
data,
|
||||
sy,
|
||||
ey,
|
||||
py,
|
||||
alpha;
|
||||
if (subsampled) {
|
||||
naturalHeight /= 2;
|
||||
}
|
||||
canvas.width = 1;
|
||||
canvas.height = naturalHeight;
|
||||
context.drawImage(img, 0, 0);
|
||||
data = context.getImageData(0, 0, 1, naturalHeight).data;
|
||||
// search image edge pixel position in case it is squashed vertically:
|
||||
sy = 0;
|
||||
ey = naturalHeight;
|
||||
py = naturalHeight;
|
||||
while (py > sy) {
|
||||
alpha = data[(py - 1) * 4 + 3];
|
||||
if (alpha === 0) {
|
||||
ey = py;
|
||||
} else {
|
||||
sy = py;
|
||||
}
|
||||
py = (ey + sy) >> 1;
|
||||
}
|
||||
return (py / naturalHeight) || 1;
|
||||
};
|
||||
|
||||
// Renders image to canvas while working around iOS image scaling bugs:
|
||||
// https://github.com/blueimp/JavaScript-Load-Image/issues/13
|
||||
loadImage.renderImageToCanvas = function (
|
||||
canvas,
|
||||
img,
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourceWidth,
|
||||
sourceHeight,
|
||||
destX,
|
||||
destY,
|
||||
destWidth,
|
||||
destHeight
|
||||
) {
|
||||
if (img._type === 'image/jpeg') {
|
||||
var context = canvas.getContext('2d'),
|
||||
tmpCanvas = document.createElement('canvas'),
|
||||
tileSize = 1024,
|
||||
tmpContext = tmpCanvas.getContext('2d'),
|
||||
subsampled,
|
||||
vertSquashRatio,
|
||||
tileX,
|
||||
tileY;
|
||||
tmpCanvas.width = tileSize;
|
||||
tmpCanvas.height = tileSize;
|
||||
context.save();
|
||||
subsampled = loadImage.detectSubsampling(img);
|
||||
if (subsampled) {
|
||||
sourceX /= 2;
|
||||
sourceY /= 2;
|
||||
sourceWidth /= 2;
|
||||
sourceHeight /= 2;
|
||||
}
|
||||
vertSquashRatio = loadImage.detectVerticalSquash(img, subsampled);
|
||||
if (subsampled || vertSquashRatio !== 1) {
|
||||
sourceY *= vertSquashRatio;
|
||||
destWidth = Math.ceil(tileSize * destWidth / sourceWidth);
|
||||
destHeight = Math.ceil(
|
||||
tileSize * destHeight / sourceHeight / vertSquashRatio
|
||||
);
|
||||
destY = 0;
|
||||
tileY = 0;
|
||||
while (tileY < sourceHeight) {
|
||||
destX = 0;
|
||||
tileX = 0;
|
||||
while (tileX < sourceWidth) {
|
||||
tmpContext.clearRect(0, 0, tileSize, tileSize);
|
||||
tmpContext.drawImage(
|
||||
img,
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourceWidth,
|
||||
sourceHeight,
|
||||
-tileX,
|
||||
-tileY,
|
||||
sourceWidth,
|
||||
sourceHeight
|
||||
);
|
||||
context.drawImage(
|
||||
tmpCanvas,
|
||||
0,
|
||||
0,
|
||||
tileSize,
|
||||
tileSize,
|
||||
destX,
|
||||
destY,
|
||||
destWidth,
|
||||
destHeight
|
||||
);
|
||||
tileX += tileSize;
|
||||
destX += destWidth;
|
||||
}
|
||||
tileY += tileSize;
|
||||
destY += destHeight;
|
||||
}
|
||||
context.restore();
|
||||
return canvas;
|
||||
}
|
||||
}
|
||||
return originalRenderMethod(
|
||||
canvas,
|
||||
img,
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourceWidth,
|
||||
sourceHeight,
|
||||
destX,
|
||||
destY,
|
||||
destWidth,
|
||||
destHeight
|
||||
);
|
||||
};
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* JavaScript Load Image Meta 1.0.2
|
||||
* https://github.com/blueimp/JavaScript-Load-Image
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Image meta data handling implementation
|
||||
* based on the help and contribution of
|
||||
* Achim Stöhr.
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/*jslint continue:true */
|
||||
/*global define, window, DataView, Blob, Uint8Array, console */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['load-image'], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(window.loadImage);
|
||||
}
|
||||
}(function (loadImage) {
|
||||
'use strict';
|
||||
|
||||
var hasblobSlice = window.Blob && (Blob.prototype.slice ||
|
||||
Blob.prototype.webkitSlice || Blob.prototype.mozSlice);
|
||||
|
||||
loadImage.blobSlice = hasblobSlice && function () {
|
||||
var slice = this.slice || this.webkitSlice || this.mozSlice;
|
||||
return slice.apply(this, arguments);
|
||||
};
|
||||
|
||||
loadImage.metaDataParsers = {
|
||||
jpeg: {
|
||||
0xffe1: [] // APP1 marker
|
||||
}
|
||||
};
|
||||
|
||||
// Parses image meta data and calls the callback with an object argument
|
||||
// with the following properties:
|
||||
// * imageHead: The complete image head as ArrayBuffer (Uint8Array for IE10)
|
||||
// The options arguments accepts an object and supports the following properties:
|
||||
// * maxMetaDataSize: Defines the maximum number of bytes to parse.
|
||||
// * disableImageHead: Disables creating the imageHead property.
|
||||
loadImage.parseMetaData = function (file, callback, options) {
|
||||
options = options || {};
|
||||
var that = this,
|
||||
// 256 KiB should contain all EXIF/ICC/IPTC segments:
|
||||
maxMetaDataSize = options.maxMetaDataSize || 262144,
|
||||
data = {},
|
||||
noMetaData = !(window.DataView && file && file.size >= 12 &&
|
||||
file.type === 'image/jpeg' && loadImage.blobSlice);
|
||||
if (noMetaData || !loadImage.readFile(
|
||||
loadImage.blobSlice.call(file, 0, maxMetaDataSize),
|
||||
function (e) {
|
||||
if (e.target.error) {
|
||||
// FileReader error
|
||||
console.log(e.target.error);
|
||||
callback(data);
|
||||
return;
|
||||
}
|
||||
// Note on endianness:
|
||||
// Since the marker and length bytes in JPEG files are always
|
||||
// stored in big endian order, we can leave the endian parameter
|
||||
// of the DataView methods undefined, defaulting to big endian.
|
||||
var buffer = e.target.result,
|
||||
dataView = new DataView(buffer),
|
||||
offset = 2,
|
||||
maxOffset = dataView.byteLength - 4,
|
||||
headLength = offset,
|
||||
markerBytes,
|
||||
markerLength,
|
||||
parsers,
|
||||
i;
|
||||
// Check for the JPEG marker (0xffd8):
|
||||
if (dataView.getUint16(0) === 0xffd8) {
|
||||
while (offset < maxOffset) {
|
||||
markerBytes = dataView.getUint16(offset);
|
||||
// Search for APPn (0xffeN) and COM (0xfffe) markers,
|
||||
// which contain application-specific meta-data like
|
||||
// Exif, ICC and IPTC data and text comments:
|
||||
if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) ||
|
||||
markerBytes === 0xfffe) {
|
||||
// The marker bytes (2) are always followed by
|
||||
// the length bytes (2), indicating the length of the
|
||||
// marker segment, which includes the length bytes,
|
||||
// but not the marker bytes, so we add 2:
|
||||
markerLength = dataView.getUint16(offset + 2) + 2;
|
||||
if (offset + markerLength > dataView.byteLength) {
|
||||
console.log('Invalid meta data: Invalid segment size.');
|
||||
break;
|
||||
}
|
||||
parsers = loadImage.metaDataParsers.jpeg[markerBytes];
|
||||
if (parsers) {
|
||||
for (i = 0; i < parsers.length; i += 1) {
|
||||
parsers[i].call(
|
||||
that,
|
||||
dataView,
|
||||
offset,
|
||||
markerLength,
|
||||
data,
|
||||
options
|
||||
);
|
||||
}
|
||||
}
|
||||
offset += markerLength;
|
||||
headLength = offset;
|
||||
} else {
|
||||
// Not an APPn or COM marker, probably safe to
|
||||
// assume that this is the end of the meta data
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Meta length must be longer than JPEG marker (2)
|
||||
// plus APPn marker (2), followed by length bytes (2):
|
||||
if (!options.disableImageHead && headLength > 6) {
|
||||
if (buffer.slice) {
|
||||
data.imageHead = buffer.slice(0, headLength);
|
||||
} else {
|
||||
// Workaround for IE10, which does not yet
|
||||
// support ArrayBuffer.slice:
|
||||
data.imageHead = new Uint8Array(buffer)
|
||||
.subarray(0, headLength);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('Invalid JPEG file: Missing JPEG marker.');
|
||||
}
|
||||
callback(data);
|
||||
},
|
||||
'readAsArrayBuffer'
|
||||
)) {
|
||||
callback(data);
|
||||
}
|
||||
};
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* JavaScript Load Image Orientation 1.1.0
|
||||
* https://github.com/blueimp/JavaScript-Load-Image
|
||||
*
|
||||
* Copyright 2013, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/*global define, window */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['load-image'], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(window.loadImage);
|
||||
}
|
||||
}(function (loadImage) {
|
||||
'use strict';
|
||||
|
||||
var originalHasCanvasOption = loadImage.hasCanvasOption,
|
||||
originalTransformCoordinates = loadImage.transformCoordinates,
|
||||
originalGetTransformedOptions = loadImage.getTransformedOptions;
|
||||
|
||||
// This method is used to determine if the target image
|
||||
// should be a canvas element:
|
||||
loadImage.hasCanvasOption = function (options) {
|
||||
return originalHasCanvasOption.call(loadImage, options) ||
|
||||
options.orientation;
|
||||
};
|
||||
|
||||
// Transform image orientation based on
|
||||
// the given EXIF orientation option:
|
||||
loadImage.transformCoordinates = function (canvas, options) {
|
||||
originalTransformCoordinates.call(loadImage, canvas, options);
|
||||
var ctx = canvas.getContext('2d'),
|
||||
width = canvas.width,
|
||||
height = canvas.height,
|
||||
orientation = options.orientation;
|
||||
if (!orientation || orientation > 8) {
|
||||
return;
|
||||
}
|
||||
if (orientation > 4) {
|
||||
canvas.width = height;
|
||||
canvas.height = width;
|
||||
}
|
||||
switch (orientation) {
|
||||
case 2:
|
||||
// horizontal flip
|
||||
ctx.translate(width, 0);
|
||||
ctx.scale(-1, 1);
|
||||
break;
|
||||
case 3:
|
||||
// 180° rotate left
|
||||
ctx.translate(width, height);
|
||||
ctx.rotate(Math.PI);
|
||||
break;
|
||||
case 4:
|
||||
// vertical flip
|
||||
ctx.translate(0, height);
|
||||
ctx.scale(1, -1);
|
||||
break;
|
||||
case 5:
|
||||
// vertical flip + 90 rotate right
|
||||
ctx.rotate(0.5 * Math.PI);
|
||||
ctx.scale(1, -1);
|
||||
break;
|
||||
case 6:
|
||||
// 90° rotate right
|
||||
ctx.rotate(0.5 * Math.PI);
|
||||
ctx.translate(0, -height);
|
||||
break;
|
||||
case 7:
|
||||
// horizontal flip + 90 rotate right
|
||||
ctx.rotate(0.5 * Math.PI);
|
||||
ctx.translate(width, -height);
|
||||
ctx.scale(-1, 1);
|
||||
break;
|
||||
case 8:
|
||||
// 90° rotate left
|
||||
ctx.rotate(-0.5 * Math.PI);
|
||||
ctx.translate(-width, 0);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// Transforms coordinate and dimension options
|
||||
// based on the given orientation option:
|
||||
loadImage.getTransformedOptions = function (img, opts) {
|
||||
var options = originalGetTransformedOptions.call(loadImage, img, opts),
|
||||
orientation = options.orientation,
|
||||
newOptions,
|
||||
i;
|
||||
if (!orientation || orientation > 8 || orientation === 1) {
|
||||
return options;
|
||||
}
|
||||
newOptions = {};
|
||||
for (i in options) {
|
||||
if (options.hasOwnProperty(i)) {
|
||||
newOptions[i] = options[i];
|
||||
}
|
||||
}
|
||||
switch (options.orientation) {
|
||||
case 2:
|
||||
// horizontal flip
|
||||
newOptions.left = options.right;
|
||||
newOptions.right = options.left;
|
||||
break;
|
||||
case 3:
|
||||
// 180° rotate left
|
||||
newOptions.left = options.right;
|
||||
newOptions.top = options.bottom;
|
||||
newOptions.right = options.left;
|
||||
newOptions.bottom = options.top;
|
||||
break;
|
||||
case 4:
|
||||
// vertical flip
|
||||
newOptions.top = options.bottom;
|
||||
newOptions.bottom = options.top;
|
||||
break;
|
||||
case 5:
|
||||
// vertical flip + 90 rotate right
|
||||
newOptions.left = options.top;
|
||||
newOptions.top = options.left;
|
||||
newOptions.right = options.bottom;
|
||||
newOptions.bottom = options.right;
|
||||
break;
|
||||
case 6:
|
||||
// 90° rotate right
|
||||
newOptions.left = options.top;
|
||||
newOptions.top = options.right;
|
||||
newOptions.right = options.bottom;
|
||||
newOptions.bottom = options.left;
|
||||
break;
|
||||
case 7:
|
||||
// horizontal flip + 90 rotate right
|
||||
newOptions.left = options.bottom;
|
||||
newOptions.top = options.right;
|
||||
newOptions.right = options.top;
|
||||
newOptions.bottom = options.left;
|
||||
break;
|
||||
case 8:
|
||||
// 90° rotate left
|
||||
newOptions.left = options.bottom;
|
||||
newOptions.top = options.left;
|
||||
newOptions.right = options.top;
|
||||
newOptions.bottom = options.right;
|
||||
break;
|
||||
}
|
||||
if (options.orientation > 4) {
|
||||
newOptions.maxWidth = options.maxHeight;
|
||||
newOptions.maxHeight = options.maxWidth;
|
||||
newOptions.minWidth = options.minHeight;
|
||||
newOptions.minHeight = options.minWidth;
|
||||
newOptions.sourceWidth = options.sourceHeight;
|
||||
newOptions.sourceHeight = options.sourceWidth;
|
||||
}
|
||||
return newOptions;
|
||||
};
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* JavaScript Load Image 1.10.0
|
||||
* https://github.com/blueimp/JavaScript-Load-Image
|
||||
*
|
||||
* Copyright 2011, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/*jslint nomen: true */
|
||||
/*global define, window, document, URL, webkitURL, Blob, File, FileReader */
|
||||
|
||||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
// Loads an image for a given File object.
|
||||
// Invokes the callback with an img or optional canvas
|
||||
// element (if supported by the browser) as parameter:
|
||||
var loadImage = function (file, callback, options) {
|
||||
var img = document.createElement('img'),
|
||||
url,
|
||||
oUrl;
|
||||
img.onerror = callback;
|
||||
img.onload = function () {
|
||||
if (oUrl && !(options && options.noRevoke)) {
|
||||
loadImage.revokeObjectURL(oUrl);
|
||||
}
|
||||
if (callback) {
|
||||
callback(loadImage.scale(img, options));
|
||||
}
|
||||
};
|
||||
if (loadImage.isInstanceOf('Blob', file) ||
|
||||
// Files are also Blob instances, but some browsers
|
||||
// (Firefox 3.6) support the File API but not Blobs:
|
||||
loadImage.isInstanceOf('File', file)) {
|
||||
url = oUrl = loadImage.createObjectURL(file);
|
||||
// Store the file type for resize processing:
|
||||
img._type = file.type;
|
||||
} else if (typeof file === 'string') {
|
||||
url = file;
|
||||
if (options && options.crossOrigin) {
|
||||
img.crossOrigin = options.crossOrigin;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (url) {
|
||||
img.src = url;
|
||||
return img;
|
||||
}
|
||||
return loadImage.readFile(file, function (e) {
|
||||
var target = e.target;
|
||||
if (target && target.result) {
|
||||
img.src = target.result;
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// The check for URL.revokeObjectURL fixes an issue with Opera 12,
|
||||
// which provides URL.createObjectURL but doesn't properly implement it:
|
||||
urlAPI = (window.createObjectURL && window) ||
|
||||
(window.URL && URL.revokeObjectURL && URL) ||
|
||||
(window.webkitURL && webkitURL);
|
||||
|
||||
loadImage.isInstanceOf = function (type, obj) {
|
||||
// Cross-frame instanceof check
|
||||
return Object.prototype.toString.call(obj) === '[object ' + type + ']';
|
||||
};
|
||||
|
||||
// Transform image coordinates, allows to override e.g.
|
||||
// the canvas orientation based on the orientation option,
|
||||
// gets canvas, options passed as arguments:
|
||||
loadImage.transformCoordinates = function () {
|
||||
return;
|
||||
};
|
||||
|
||||
// Returns transformed options, allows to override e.g.
|
||||
// maxWidth, maxHeight and crop options based on the aspectRatio.
|
||||
// gets img, options passed as arguments:
|
||||
loadImage.getTransformedOptions = function (img, options) {
|
||||
var aspectRatio = options.aspectRatio,
|
||||
newOptions,
|
||||
i,
|
||||
width,
|
||||
height;
|
||||
if (!aspectRatio) {
|
||||
return options;
|
||||
}
|
||||
newOptions = {};
|
||||
for (i in options) {
|
||||
if (options.hasOwnProperty(i)) {
|
||||
newOptions[i] = options[i];
|
||||
}
|
||||
}
|
||||
newOptions.crop = true;
|
||||
width = img.naturalWidth || img.width;
|
||||
height = img.naturalHeight || img.height;
|
||||
if (width / height > aspectRatio) {
|
||||
newOptions.maxWidth = height * aspectRatio;
|
||||
newOptions.maxHeight = height;
|
||||
} else {
|
||||
newOptions.maxWidth = width;
|
||||
newOptions.maxHeight = width / aspectRatio;
|
||||
}
|
||||
return newOptions;
|
||||
};
|
||||
|
||||
// Canvas render method, allows to override the
|
||||
// rendering e.g. to work around issues on iOS:
|
||||
loadImage.renderImageToCanvas = function (
|
||||
canvas,
|
||||
img,
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourceWidth,
|
||||
sourceHeight,
|
||||
destX,
|
||||
destY,
|
||||
destWidth,
|
||||
destHeight
|
||||
) {
|
||||
canvas.getContext('2d').drawImage(
|
||||
img,
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourceWidth,
|
||||
sourceHeight,
|
||||
destX,
|
||||
destY,
|
||||
destWidth,
|
||||
destHeight
|
||||
);
|
||||
return canvas;
|
||||
};
|
||||
|
||||
// This method is used to determine if the target image
|
||||
// should be a canvas element:
|
||||
loadImage.hasCanvasOption = function (options) {
|
||||
return options.canvas || options.crop || options.aspectRatio;
|
||||
};
|
||||
|
||||
// Scales and/or crops the given image (img or canvas HTML element)
|
||||
// using the given options.
|
||||
// Returns a canvas object if the browser supports canvas
|
||||
// and the hasCanvasOption method returns true or a canvas
|
||||
// object is passed as image, else the scaled image:
|
||||
loadImage.scale = function (img, options) {
|
||||
options = options || {};
|
||||
var canvas = document.createElement('canvas'),
|
||||
useCanvas = img.getContext ||
|
||||
(loadImage.hasCanvasOption(options) && canvas.getContext),
|
||||
width = img.naturalWidth || img.width,
|
||||
height = img.naturalHeight || img.height,
|
||||
destWidth = width,
|
||||
destHeight = height,
|
||||
maxWidth,
|
||||
maxHeight,
|
||||
minWidth,
|
||||
minHeight,
|
||||
sourceWidth,
|
||||
sourceHeight,
|
||||
sourceX,
|
||||
sourceY,
|
||||
tmp,
|
||||
scaleUp = function () {
|
||||
var scale = Math.max(
|
||||
(minWidth || destWidth) / destWidth,
|
||||
(minHeight || destHeight) / destHeight
|
||||
);
|
||||
if (scale > 1) {
|
||||
destWidth = destWidth * scale;
|
||||
destHeight = destHeight * scale;
|
||||
}
|
||||
},
|
||||
scaleDown = function () {
|
||||
var scale = Math.min(
|
||||
(maxWidth || destWidth) / destWidth,
|
||||
(maxHeight || destHeight) / destHeight
|
||||
);
|
||||
if (scale < 1) {
|
||||
destWidth = destWidth * scale;
|
||||
destHeight = destHeight * scale;
|
||||
}
|
||||
};
|
||||
if (useCanvas) {
|
||||
options = loadImage.getTransformedOptions(img, options);
|
||||
sourceX = options.left || 0;
|
||||
sourceY = options.top || 0;
|
||||
if (options.sourceWidth) {
|
||||
sourceWidth = options.sourceWidth;
|
||||
if (options.right !== undefined && options.left === undefined) {
|
||||
sourceX = width - sourceWidth - options.right;
|
||||
}
|
||||
} else {
|
||||
sourceWidth = width - sourceX - (options.right || 0);
|
||||
}
|
||||
if (options.sourceHeight) {
|
||||
sourceHeight = options.sourceHeight;
|
||||
if (options.bottom !== undefined && options.top === undefined) {
|
||||
sourceY = height - sourceHeight - options.bottom;
|
||||
}
|
||||
} else {
|
||||
sourceHeight = height - sourceY - (options.bottom || 0);
|
||||
}
|
||||
destWidth = sourceWidth;
|
||||
destHeight = sourceHeight;
|
||||
}
|
||||
maxWidth = options.maxWidth;
|
||||
maxHeight = options.maxHeight;
|
||||
minWidth = options.minWidth;
|
||||
minHeight = options.minHeight;
|
||||
if (useCanvas && maxWidth && maxHeight && options.crop) {
|
||||
destWidth = maxWidth;
|
||||
destHeight = maxHeight;
|
||||
tmp = sourceWidth / sourceHeight - maxWidth / maxHeight;
|
||||
if (tmp < 0) {
|
||||
sourceHeight = maxHeight * sourceWidth / maxWidth;
|
||||
if (options.top === undefined && options.bottom === undefined) {
|
||||
sourceY = (height - sourceHeight) / 2;
|
||||
}
|
||||
} else if (tmp > 0) {
|
||||
sourceWidth = maxWidth * sourceHeight / maxHeight;
|
||||
if (options.left === undefined && options.right === undefined) {
|
||||
sourceX = (width - sourceWidth) / 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (options.contain || options.cover) {
|
||||
minWidth = maxWidth = maxWidth || minWidth;
|
||||
minHeight = maxHeight = maxHeight || minHeight;
|
||||
}
|
||||
if (options.cover) {
|
||||
scaleDown();
|
||||
scaleUp();
|
||||
} else {
|
||||
scaleUp();
|
||||
scaleDown();
|
||||
}
|
||||
}
|
||||
if (useCanvas) {
|
||||
canvas.width = destWidth;
|
||||
canvas.height = destHeight;
|
||||
loadImage.transformCoordinates(
|
||||
canvas,
|
||||
options
|
||||
);
|
||||
return loadImage.renderImageToCanvas(
|
||||
canvas,
|
||||
img,
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourceWidth,
|
||||
sourceHeight,
|
||||
0,
|
||||
0,
|
||||
destWidth,
|
||||
destHeight
|
||||
);
|
||||
}
|
||||
img.width = destWidth;
|
||||
img.height = destHeight;
|
||||
return img;
|
||||
};
|
||||
|
||||
loadImage.createObjectURL = function (file) {
|
||||
return urlAPI ? urlAPI.createObjectURL(file) : false;
|
||||
};
|
||||
|
||||
loadImage.revokeObjectURL = function (url) {
|
||||
return urlAPI ? urlAPI.revokeObjectURL(url) : false;
|
||||
};
|
||||
|
||||
// Loads a given File object via FileReader interface,
|
||||
// invokes the callback with the event object (load or error).
|
||||
// The result can be read via event.target.result:
|
||||
loadImage.readFile = function (file, callback, method) {
|
||||
if (window.FileReader) {
|
||||
var fileReader = new FileReader();
|
||||
fileReader.onload = fileReader.onerror = callback;
|
||||
method = method || 'readAsDataURL';
|
||||
if (fileReader[method]) {
|
||||
fileReader[method](file);
|
||||
return fileReader;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(function () {
|
||||
return loadImage;
|
||||
});
|
||||
} else {
|
||||
$.loadImage = loadImage;
|
||||
}
|
||||
}(this));
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "blueimp-load-image",
|
||||
"version": "1.13.0",
|
||||
"title": "JavaScript Load Image",
|
||||
"description": "JavaScript Load Image is a library to load images provided as File or Blob objects or via URL. It returns an optionally scaled and/or cropped HTML img or canvas element. It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"load",
|
||||
"loading",
|
||||
"image",
|
||||
"file",
|
||||
"blob",
|
||||
"url",
|
||||
"scale",
|
||||
"crop",
|
||||
"img",
|
||||
"canvas",
|
||||
"meta",
|
||||
"exif",
|
||||
"thumbnail",
|
||||
"resizing"
|
||||
],
|
||||
"homepage": "https://github.com/blueimp/JavaScript-Load-Image",
|
||||
"author": {
|
||||
"name": "Sebastian Tschan",
|
||||
"url": "https://blueimp.net"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Sebastian Tschan",
|
||||
"url": "https://blueimp.net"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/blueimp/JavaScript-Load-Image.git"
|
||||
},
|
||||
"bugs": "https://github.com/blueimp/JavaScript-Load-Image/issues",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://www.opensource.org/licenses/MIT"
|
||||
}
|
||||
],
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.5",
|
||||
"grunt-contrib-uglify": "~0.5.1",
|
||||
"grunt-contrib-jshint": "~0.10.0",
|
||||
"grunt-bump-build-git": "~1.1.1",
|
||||
"grunt-mocha": "~0.4.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* JavaScript Templates 2.4.1
|
||||
* https://github.com/blueimp/JavaScript-Templates
|
||||
*
|
||||
* Copyright 2011, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*
|
||||
* Inspired by John Resig's JavaScript Micro-Templating:
|
||||
* http://ejohn.org/blog/javascript-micro-templating/
|
||||
*/
|
||||
|
||||
/*jslint evil: true, regexp: true, unparam: true */
|
||||
/*global document, define */
|
||||
|
||||
(function ($) {
|
||||
"use strict";
|
||||
var tmpl = function (str, data) {
|
||||
var f = !/[^\w\-\.:]/.test(str) ? tmpl.cache[str] = tmpl.cache[str] ||
|
||||
tmpl(tmpl.load(str)) :
|
||||
new Function(
|
||||
tmpl.arg + ',tmpl',
|
||||
"var _e=tmpl.encode" + tmpl.helper + ",_s='" +
|
||||
str.replace(tmpl.regexp, tmpl.func) +
|
||||
"';return _s;"
|
||||
);
|
||||
return data ? f(data, tmpl) : function (data) {
|
||||
return f(data, tmpl);
|
||||
};
|
||||
};
|
||||
tmpl.cache = {};
|
||||
tmpl.load = function (id) {
|
||||
return document.getElementById(id).innerHTML;
|
||||
};
|
||||
tmpl.regexp = /([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g;
|
||||
tmpl.func = function (s, p1, p2, p3, p4, p5) {
|
||||
if (p1) { // whitespace, quote and backspace in HTML context
|
||||
return {
|
||||
"\n": "\\n",
|
||||
"\r": "\\r",
|
||||
"\t": "\\t",
|
||||
" " : " "
|
||||
}[p1] || "\\" + p1;
|
||||
}
|
||||
if (p2) { // interpolation: {%=prop%}, or unescaped: {%#prop%}
|
||||
if (p2 === "=") {
|
||||
return "'+_e(" + p3 + ")+'";
|
||||
}
|
||||
return "'+(" + p3 + "==null?'':" + p3 + ")+'";
|
||||
}
|
||||
if (p4) { // evaluation start tag: {%
|
||||
return "';";
|
||||
}
|
||||
if (p5) { // evaluation end tag: %}
|
||||
return "_s+='";
|
||||
}
|
||||
};
|
||||
tmpl.encReg = /[<>&"'\x00]/g;
|
||||
tmpl.encMap = {
|
||||
"<" : "<",
|
||||
">" : ">",
|
||||
"&" : "&",
|
||||
"\"" : """,
|
||||
"'" : "'"
|
||||
};
|
||||
tmpl.encode = function (s) {
|
||||
/*jshint eqnull:true */
|
||||
return (s == null ? "" : "" + s).replace(
|
||||
tmpl.encReg,
|
||||
function (c) {
|
||||
return tmpl.encMap[c] || "";
|
||||
}
|
||||
);
|
||||
};
|
||||
tmpl.arg = "o";
|
||||
tmpl.helper = ",print=function(s,e){_s+=e?(s==null?'':s):_e(s);}" +
|
||||
",include=function(s,d){_s+=tmpl(s,d);}";
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(function () {
|
||||
return tmpl;
|
||||
});
|
||||
} else {
|
||||
$.tmpl = tmpl;
|
||||
}
|
||||
}(this));
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){"use strict";var b=function(a,c){var d=/[^\w\-\.:]/.test(a)?new Function(b.arg+",tmpl","var _e=tmpl.encode"+b.helper+",_s='"+a.replace(b.regexp,b.func)+"';return _s;"):b.cache[a]=b.cache[a]||b(b.load(a));return c?d(c,b):function(a){return d(a,b)}};b.cache={},b.load=function(a){return document.getElementById(a).innerHTML},b.regexp=/([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,b.func=function(a,b,c,d,e,f){return b?{"\n":"\\n","\r":"\\r"," ":"\\t"," ":" "}[b]||"\\"+b:c?"="===c?"'+_e("+d+")+'":"'+("+d+"==null?'':"+d+")+'":e?"';":f?"_s+='":void 0},b.encReg=/[<>&"'\x00]/g,b.encMap={"<":"<",">":">","&":"&",'"':""","'":"'"},b.encode=function(a){return(null==a?"":""+a).replace(b.encReg,function(a){return b.encMap[a]||""})},b.arg="o",b.helper=",print=function(s,e){_s+=e?(s==null?'':s):_e(s);},include=function(s,d){_s+=tmpl(s,d);}","function"==typeof define&&define.amd?define(function(){return b}):a.tmpl=b}(this);
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "blueimp-tmpl",
|
||||
"version": "2.5.4",
|
||||
"title": "JavaScript Templates",
|
||||
"description": "< 1KB lightweight, fast & powerful JavaScript templating engine with zero dependencies. Compatible with server-side environments like node.js, module loaders like RequireJS and all web browsers.",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"templates",
|
||||
"templating"
|
||||
],
|
||||
"homepage": "https://github.com/blueimp/JavaScript-Templates",
|
||||
"author": {
|
||||
"name": "Sebastian Tschan",
|
||||
"url": "https://blueimp.net"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Sebastian Tschan",
|
||||
"url": "https://blueimp.net"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/blueimp/JavaScript-Templates.git"
|
||||
},
|
||||
"bugs": "https://github.com/blueimp/JavaScript-Templates/issues",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://www.opensource.org/licenses/MIT"
|
||||
}
|
||||
],
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.5",
|
||||
"grunt-contrib-uglify": "~0.5.0",
|
||||
"grunt-contrib-jshint": "~0.10.0",
|
||||
"grunt-bump-build-git": "~1.1.1",
|
||||
"grunt-simple-mocha": "~0.4.0",
|
||||
"grunt-mocha": "~0.4.11",
|
||||
"expect.js": "0.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "grunt test"
|
||||
},
|
||||
"bin": {
|
||||
"tmpl.js": "js/compile.js"
|
||||
},
|
||||
"main": "js/tmpl.js"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
// Arabic (ar)
|
||||
plupload.addI18n({"Stop Upload":"أيقاف التحميل","Upload URL might be wrong or doesn't exist.":"عنوان التحميل ربما يكون خاطئ أو غير متوفر","tb":"تيرابايت","Size":"الحجم","Close":"أغلاق","Init error.":"خطأ في تهيئة","Add files to the upload queue and click the start button.":"أضف ملفات إلى القائمة إنتظار التحميل ثم أضغط على زر البداية","Filename":"أسم الملف","Image format either wrong or not supported.":"صيغة الصورة أما خطاء أو غير مدعومه","Status":"الحالة","HTTP Error.":"خطأ في برتوكول نقل الملفات","Start Upload":"أبدا التحميل","mb":"ميجابايت","kb":"كيلوبايت","Duplicate file error.":"خطاء في تكرار الملف","File size error.":"خطأ في حجم الملف","N/A":"لا شي","gb":"جيجابايت","Error: Invalid file extension:":"خطاء : أمتداد الملف غير صالح :","Select files":"أختر الملفات","%s already present in the queue.":"%s الملف موجود بالفعل في قائمة الانتظار","File: %s":"ملف: %s","b":"بايت","Uploaded %d/%d files":"تحميل %d/%d ملف","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"العناصر المقبوله لتحميل هي %d ملف في هذا الوقت. الملفات الاضافية أزيلة.","%d files queued":"%d الملفات في قائمة الانتظار","File: %s, size: %d, max file size: %d":"ملف: %s, أقصى حجم للملف: %d, حجم: %d","Drag files here.":"سحب الملف هنا","Runtime ran out of available memory.":"الذاكرة المتوفره أنتهت لمدة التشغيل","File count error.":"خطاء في عد الملفات","File extension error.":"خطأ في أمتداد الملف","Error: File too large:":" خطاء : حجم الملف كبير :","Add Files":"أضف ملفات"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Azerbaijani (az)
|
||||
plupload.addI18n({"Stop Upload":"Yükləməni saxla","Upload URL might be wrong or doesn't exist.":"Yükləmə ünvanı səhvdir və ya mövcud deyil","tb":"tb","Size":"Həcm","Close":"Bağla","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Faylları əlavə edin və yüklə düyməsinə klikləyin.","Filename":"Faylın adı","Image format either wrong or not supported.":"Şəklin formatı uyğun deyil və ya dəstəklənmir.","Status":"Status","HTTP Error.":"HTTP xətası.","Start Upload":"Yüklə","mb":"mb","kb":"kb","Duplicate file error.":"Bu fayl artıq növbədə var.","File size error.":"Fayl həcmi xətası.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Xəta: Yanlış fayl uzantısı:","Select files":"Faylları seçin","%s already present in the queue.":"%s artıq növbədə var.","File: %s":"Fayl: %s","b":"b","Uploaded %d/%d files":"%d/%d fayl yüklənib","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"Növbədə %d fayl var","File: %s, size: %d, max file size: %d":"Fayl: %s, həcm: %d, max fayl həcmi: %d","Drag files here.":"Faylları bura çəkin.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Fayl sayı çox böyükdür.","File extension error.":"Fayl uzantısı xətası.","Error: File too large:":"Xəta:Fayl həcmi çox böyükdür.","Add Files":"Fayl əlavə et"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Bulgarian (bg)
|
||||
plupload.addI18n({"Stop Upload":"Спрете качването","Upload URL might be wrong or doesn't exist.":"URL за качване може да е грешен или да не съществува.","tb":"tb","Size":"Размер","Close":"Затвори","Init error.":"Грешка: инициализиране.","Add files to the upload queue and click the start button.":"Добавете файлове в опашката за качване, и щракнете бутона старт.","Filename":"Име на файла","Image format either wrong or not supported.":"Формата на изображението или е объркан, или не се поддържа.","Status":"Статус","HTTP Error.":"Грешка: HTTP .","Start Upload":"Започнете качването","mb":"mb","kb":"kb","Duplicate file error.":"Грешка: файла е вече качен на сървъра.","File size error.":"Грешка: размер на файла.","N/A":"не приложимо","gb":"gb","Error: Invalid file extension:":"Грешка: Невалидно разширение на файл:","Select files":"Изберете файлове","%s already present in the queue.":"%s вече го има в опашката.","File: %s":"Файл: %s","b":"b","Uploaded %d/%d files":"Качени %d/%d файла","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Елемента за качване приема само %d файл(а) наведнъж. Допълнителните файлове бяха отстранени.","%d files queued":"%d файла в опашката","File: %s, size: %d, max file size: %d":"Файл: %s, размер: %d, максимален размер: %d","Drag files here.":"Довлечете файловете тук.","Runtime ran out of available memory.":"Недостатъчна свободна памет.","File count error.":"Грешка в броя на файловете.","File extension error.":"Грешка: разширение на файла.","Error: File too large:":"Грешка: Файла е твърде голям:","Add Files":"Добавете файлове"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Bosnian (bs)
|
||||
plupload.addI18n({"Stop Upload":"Prekini dodavanje","Upload URL might be wrong or doesn't exist.":"URL za dodavanje je neispravan ili ne postoji.","tb":"tb","Size":"Veličina","Close":"Zatvori","Init error.":"Inicijalizacijska greška.","Add files to the upload queue and click the start button.":"Dodajte datoteke u red i kliknite na dugme za pokretanje.","Filename":"Naziv datoteke","Image format either wrong or not supported.":"Format slike je neispravan ili nije podržan.","Status":"Status","HTTP Error.":"HTTP greška.","Start Upload":"Započni dodavanje","mb":"mb","kb":"kb","Duplicate file error.":"Dupla datoteka.","File size error.":"Greška u veličini datoteke.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Greška! Neispravan ekstenzija datoteke:","Select files":"Odaberite datoteke","%s already present in the queue.":"%s se već nalazi u redu.","File: %s":"Datoteka: %s","b":"b","Uploaded %d/%d files":"Dodano %d/%d datoteka","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Dodavanje trenutno dozvoljava samo %d datoteka istovremeno. Dodatne datoteke su uklonjene.","%d files queued":"%d datoteka čeka","File: %s, size: %d, max file size: %d":"Datoteka: %s, veličina: %d, maksimalna veličina: %d","Drag files here.":"Dovucite datoteke ovdje.","Runtime ran out of available memory.":"Nema više dostupne memorije.","File count error.":"Greška u brojanju datoeka.","File extension error.":"Greška u ekstenziji datoteke.","Error: File too large:":"Greška! Datoteka je prevelika:","Add Files":"Dodaj datoteke"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Catalan (ca)
|
||||
plupload.addI18n({"Stop Upload":"Parar pujada","Upload URL might be wrong or doesn't exist.":"La URL de càrrega no és correcte o bé no existeix.","tb":"Tb","Size":"Tamany","Close":"Tancar","Init error.":"Error d´inicialització.","Add files to the upload queue and click the start button.":"Afegeixi els fitxers a la cua de pujada i cliqui el botó Iniciar","Filename":"Nom de fitxer","Image format either wrong or not supported.":"Format d'imatge incorrecte o no suportat.","Status":"Estat","HTTP Error.":"Error HTTP.","Start Upload":"Començar pujada","mb":"Mb","kb":"Kb","Duplicate file error.":"Error per duplicitat de fitxer.","File size error.":"Error en la mida del fitxer.","N/A":"N/D","gb":"Gb","Error: Invalid file extension:":"Error: Extensió de fitxer no vàlida:","Select files":"Seleccionar fitxers","%s already present in the queue.":"%s ja existeix a la cua.","File: %s":"Fitxer: %s","b":"b","Uploaded %d/%d files":"Pujats %d/%d fitxers","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"La càrrega d'elements tan sols accepta %d fitxer(s) alhora. Els fitxers sobrants seran descartats.","%d files queued":"%d fitxers en cua","File: %s, size: %d, max file size: %d":"Fitxer: %s, mida: %d, mida màxima de fitxer: %d","Drag files here.":"Arrossegui fitxers aquí","Runtime ran out of available memory.":"L'execució ha arribat al límit de memòria.","File count error.":"Error en el recompte de fitxers","File extension error.":"Error en l´extensió del fitxer.","Error: File too large:":"Error: Fitxer massa gran:","Add Files":"Afegir fitxers"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Czech (cs)
|
||||
plupload.addI18n({"Stop Upload":"Zastavit nahrávání","Upload URL might be wrong or doesn't exist.":"URL uploadu je možná špatně, nebo neexistuje.","tb":"tb","Size":"Velikost","Close":"Zavřít","Init error.":"Chyba inicializace.","Add files to the upload queue and click the start button.":"Přidejte soubory do fronty a pak spusťte nahrávání.","Filename":"Název souboru","Image format either wrong or not supported.":"Špatný, nebo nepodporovaný formát obrázku.","Status":"Stav","HTTP Error.":"Chyba HTTP.","Start Upload":"Spustit nahrávání","mb":"mb","kb":"kb","Duplicate file error.":"Chyba - duplikovaný soubor.","File size error.":"Chyba velikosti souboru.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Chyba: Neplatná koncovka souboru:","Select files":"Vyberte soubory","%s already present in the queue.":"%s je již zařazen ve frontě.","File: %s":"Soubor: %s","b":"b","Uploaded %d/%d files":"Nahráno %d/%d souborů","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload akceptuje pouze %d soubor(ů) najednou. Další soubory byly odstraněny.","%d files queued":"%d souborů ve frontě","File: %s, size: %d, max file size: %d":"Soubor: %s, velikost: %d, maximální velikost souboru: %d","Drag files here.":"Sem přetáhněte soubory.","Runtime ran out of available memory.":"Běh skriptu přesáhl dostupnou paměť.","File count error.":"Chyba v počtu souborů.","File extension error.":"Chyba přípony souboru.","Error: File too large:":"Chyba: Soubor je příliš veliký:","Add Files":"Přidat soubory"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Welsh (cy)
|
||||
plupload.addI18n({"Stop Upload":"Atal Lanlwytho","Upload URL might be wrong or doesn't exist.":"URL y lanlwythiad ynb anghywir neu ddim yn bodoli.","tb":"tb","Size":"Maint","Close":"Cau","Init error.":"Gwall cych.","Add files to the upload queue and click the start button.":"Ychwanegwch ffeiliau i'r ciw lanlwytho a chlicio'r botwm dechrau.","Filename":"Enw'r ffeil","Image format either wrong or not supported.":"Fformat delwedd yn anghywir neu heb ei gynnal.","Status":"Statws","HTTP Error.":"Gwall HTTP.","Start Upload":"Dechrau Lanlwytho","mb":"mb","kb":"kb","Duplicate file error.":"Gwall ffeil ddyblyg.","File size error.":"Gwall maint ffeil.","N/A":"Dd/A","gb":"gb","Error: Invalid file extension:":"Gwall: estyniad ffeil annilys:","Select files":"Dewis ffeiliau","%s already present in the queue.":"%s yn y ciw yn barod.","File: %s":"Ffeil: %s","b":"b","Uploaded %d/%d files":"Lanlwythwyd %d/%d ffeil","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Mae'r elfen lanlwytho yn derbyn %d ffeil ar y tro. Caiff ffeiliau ychwanegol eu tynnu.","%d files queued":"%d ffeil mewn ciw","File: %s, size: %d, max file size: %d":"Ffeil: %s, maint: %d, maint mwyaf ffeil: %d","Drag files here.":"Llusgwch ffeiliau yma.","Runtime ran out of available memory.":"Allan o gof.","File count error.":"Gwall cyfri ffeiliau.","File extension error.":"Gwall estyniad ffeil.","Error: File too large:":"Gwall: Ffeil yn rhy fawr:","Add Files":"Ychwanegu Ffeiliau"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Danish (da)
|
||||
plupload.addI18n({"Stop Upload":"Stop upload","Upload URL might be wrong or doesn't exist.":"Upload URL kan være forkert eller ikke eksisterende.","tb":"tb","Size":"Størrelse","Close":"Luk","Init error.":"Opstarts fejl.","Add files to the upload queue and click the start button.":"Tilføj filer til køen og klik Start upload knappen.","Filename":"Filnavn","Image format either wrong or not supported.":"Billede format er enten forkert eller ikke understøttet.","Status":"Status","HTTP Error.":"HTTP fejl.","Start Upload":"Start upload","mb":"mb","kb":"kb","Duplicate file error.":"Filen findes allerede.","File size error.":"Filstørrelse fejl.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Fejl: Ugyldigt fil format:","Select files":"Vælg filer","%s already present in the queue.":"%s findes allerede i køen.","File: %s":"Fil: %s","b":"b","Uploaded %d/%d files":"Uploaded %d/%d filer","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload accepterer kun %d fil(er) af gangen. Ekstra filer blev skippet.","%d files queued":"%d filer i kø","File: %s, size: %d, max file size: %d":"Fil: %s, størrelse: %d, maks. filstørrelse: %d","Drag files here.":"Træk filer her.","Runtime ran out of available memory.":"Runtime mangler tilgængelige hukommelse.","File count error.":"Fil antal fejl.","File extension error.":"Fil format fejl.","Error: File too large:":"Fejl: Filen er for stor:","Add Files":"Tilføj filer"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// German (de)
|
||||
plupload.addI18n({"Stop Upload":"Hochladen stoppen","Upload URL might be wrong or doesn't exist.":"Upload-URL ist falsch oder existiert nicht.","tb":"TB","Size":"Größe","Close":"Schließen","Init error.":"Initialisierungsfehler","Add files to the upload queue and click the start button.":"Dateien hinzufügen und auf 'Hochladen' klicken.","Filename":"Dateiname","Image format either wrong or not supported.":"Bildformat falsch oder nicht unterstützt.","Status":"Status","HTTP Error.":"HTTP-Fehler","Start Upload":"Hochladen beginnen","mb":"MB","kb":"KB","Duplicate file error.":"Datei bereits hochgeladen","File size error.":"Fehler bei Dateigröße","N/A":"Nicht verfügbar","gb":"GB","Error: Invalid file extension:":"Fehler: Ungültige Dateiendung:","Select files":"Dateien auswählen","%s already present in the queue.":"%s ist bereits in der Warteschlange","File: %s":"Datei: %s","b":"B","Uploaded %d/%d files":"%d/%d Dateien wurden hochgeladen","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Pro Durchgang können nur %d Datei(en) akzeptiert werden. Überzählige Dateien wurden ignoriert.","%d files queued":"%d Dateien in der Warteschlange","File: %s, size: %d, max file size: %d":"Datei: %s, Größe: %d, maximale Dateigröße: %d","Drag files here.":"Dateien hier hin ziehen.","Runtime ran out of available memory.":"Nicht genügend Speicher verfügbar.","File count error.":"Fehlerhafte Dateianzahl.","File extension error.":"Fehler bei Dateiendung","Error: File too large:":"Fehler: Datei zu groß:","Add Files":"Dateien hinzufügen"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Greek (el)
|
||||
plupload.addI18n({"Stop Upload":"Ακύρωση Μεταφόρτωσης","Upload URL might be wrong or doesn't exist.":"Το URL μεταφόρτωσης είναι λάθος ή δεν υπάρχει.","tb":"tb","Size":"Μέγεθος","Close":"Κλείσιμο","Init error.":"Σφάλμα αρχικοποίησης.","Add files to the upload queue and click the start button.":"Προσθέστε αρχεία στην ουρά μεταφόρτωσης και πατήστε το κουμπί εκκίνησης.","Filename":"Όνομα Αρχείου","Image format either wrong or not supported.":"Ο τύπος εικόνας είναι λάθος ή δεν υποστηρίζεται.","Status":"Κατάσταση","HTTP Error.":"Σφάλμα HTTP.","Start Upload":"Εκκίνηση Μεταφόρτωσης","mb":"mb","kb":"kb","Duplicate file error.":"Το αρχείο έχει ξαναπροστεθεί.","File size error.":"Σφάλμα με το μέγεθος του αρχείου.","N/A":"Δεν ισχύει","gb":"gb","Error: Invalid file extension:":"Σφάλμα: Μη έγκυρος τύπος αρχείου:","Select files":"Επιλέξτε Αρχεία","%s already present in the queue.":"Το «%s» βρίσκεται ήδη στην ουρά.","File: %s":"Αρχείο: %s","b":"b","Uploaded %d/%d files":"Μεταφορτώθηκαν %d/%d αρχεία","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Μπορείτε να μεταφορτώσετε μεχρι και %d αρχείο/α κάθε φορά. Τα επιπλέον αρχεία αφαιρέθηκαν.","%d files queued":"%d αρχεία στην ουρά","File: %s, size: %d, max file size: %d":"Αρχείο: %s, μέγεθος: %d, μέγιστο μέγεθος αρχείου: %d","Drag files here.":"Σύρετε αρχεία εδώ","Runtime ran out of available memory.":"Δεν υπάρχει αρκετή διαθέσιμη μνήμη.","File count error.":"Σφάλμα με τον αριθμό αρχείων.","File extension error.":"Σφάλμα με τον τύπο αρχείου.","Error: File too large:":"Σφάλμα: Πολύ μεγάλο αρχείο:","Add Files":"Προσθέστε Αρχεία"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// English (en)
|
||||
plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Size","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Add files to the upload queue and click the start button.","Filename":"Filename","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","mb":"mb","kb":"kb","Duplicate file error.":"Duplicate file error.","File size error.":"File size error.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Select files","%s already present in the queue.":"%s already present in the queue.","File: %s":"File: %s","b":"b","Uploaded %d/%d files":"Uploaded %d/%d files","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"File: %s, size: %d, max file size: %d","Drag files here.":"Drag files here.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Spanish (es)
|
||||
plupload.addI18n({"Stop Upload":"Detener Subida.","Upload URL might be wrong or doesn't exist.":"URL de carga inexistente.","tb":"TB","Size":"Tamaño","Close":"Cerrar","Init error.":"Error de inicialización.","Add files to the upload queue and click the start button.":"Agregue archivos a la lista de subida y pulse clic en el botón de Iniciar carga","Filename":"Nombre de archivo","Image format either wrong or not supported.":"Formato de imagen no soportada.","Status":"Estado","HTTP Error.":"Error de HTTP.","Start Upload":"Iniciar carga","mb":"MB","kb":"KB","Duplicate file error.":"Error, archivo duplicado","File size error.":"Error de tamaño de archivo.","N/A":"No disponible","gb":"GB","Error: Invalid file extension:":"Error: Extensión de archivo inválida:","Select files":"Elija archivos","%s already present in the queue.":"%s ya se encuentra en la lista.","File: %s":"Archivo: %s","b":"B","Uploaded %d/%d files":"Subidos %d/%d archivos","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Se aceptan sólo %d archivo(s) al tiempo. Más, no se tienen en cuenta.","%d files queued":"%d archivos en cola.","File: %s, size: %d, max file size: %d":"Archivo: %s, tamaño: %d, tamaño máximo de archivo: %d","Drag files here.":"Arrastre archivos aquí","Runtime ran out of available memory.":"No hay memoria disponible.","File count error.":"Error en contador de archivos.","File extension error.":"Error de extensión de archivo.","Error: File too large:":"Error: archivo demasiado grande:","Add Files":"Agregar archivos"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Estonian (et)
|
||||
plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Üleslaadimise URL võib olla vale või seda pole.","tb":"","Size":"Suurus","Close":"Sulge","Init error.":"Lähtestamise viga.","Add files to the upload queue and click the start button.":"Lisa failid üleslaadimise järjekorda ja klõpsa alustamise nupule.","Filename":"Failinimi","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Olek","HTTP Error.":"HTTP ühenduse viga.","Start Upload":"Start Upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"Failisuuruse viga.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Vali faile","%s already present in the queue.":"","File: %s":"Fail: %s","b":"","Uploaded %d/%d files":"Üles laaditud %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Üleslaadimise element saab vastu võtta ainult %d faili ühe korraga. Ülejäänud failid jäetakse laadimata.","%d files queued":"Järjekorras on %d faili","File: %s, size: %d, max file size: %d":"","Drag files here.":"Lohista failid siia.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Failide arvu viga.","File extension error.":"Faililaiendi viga.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Persian (fa)
|
||||
plupload.addI18n({"Stop Upload":"توقف انتقال","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"ترابایت","Size":"سایز","Close":"بستن","Init error.":"خطا در استارت اسکریپت","Add files to the upload queue and click the start button.":"اضافه کنید فایل ها را به صف آپلود و دکمه شروع را کلیک کنید.","Filename":"نام فایل","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"وضعیت","HTTP Error.":"HTTP خطای","Start Upload":"شروع انتقال","mb":"مگابایت","kb":"کیلوبایت","Duplicate file error.":"خطای فایل تکراری","File size error.":"خطای سایز فایل","N/A":"N/A","gb":"گیگابایت","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"انتخاب فایل","%s already present in the queue.":"%s در لیست آپلود وجود دارد.","File: %s":" فایل ها : %s","b":"بایت","Uploaded %d/%d files":"منتقل شد %d/%d از فایلها","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"عنصر بارگذار فقط %d فایل رو در یک زمان می پذیرد. سایر فایل ها مجرد از این موضوع هستند.","%d files queued":"%d فایل در صف","File: %s, size: %d, max file size: %d":"فایل: %s, اندازه: %d, محدودیت اندازه فایل: %d","Drag files here.":"بکشید فایل ها رو به اینجا","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"خطای تعداد فایل","File extension error.":"خطا پیشوند فایل","Error: File too large:":"Error: File too large:","Add Files":"افزودن فایل"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Finnish (fi)
|
||||
plupload.addI18n({"Stop Upload":"Pysäytä lähetys","Upload URL might be wrong or doesn't exist.":"Lähetyksen URL-osoite saattaa olla väärä tai sitä ei ole olemassa.","tb":"TB","Size":"Koko","Close":"Sulje","Init error.":"Init virhe.","Add files to the upload queue and click the start button.":"Lisää tiedostoja lähetysjonoon ja klikkaa aloita-nappia.","Filename":"Tiedostonimi","Image format either wrong or not supported.":"Kuvaformaatti on joko väärä tai ei tuettu.","Status":"Tila","HTTP Error.":"HTTP-virhe.","Start Upload":"Aloita lähetys","mb":"MB","kb":"kB","Duplicate file error.":"Tuplatiedostovirhe.","File size error.":"Tiedostokokovirhe.","N/A":"N/A","gb":"GB","Error: Invalid file extension:":"Virhe: Virheellinen tiedostopääte:","Select files":"Valitse tiedostoja","%s already present in the queue.":"%s on jo jonossa.","File: %s":"Tiedosto: %s","b":"B","Uploaded %d/%d files":"Lähetetty %d/%d tiedostoa","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Vain %d tiedosto(a) voidaan lähettää kerralla. Ylimääräiset tiedostot ohitettiin.","%d files queued":"%d tiedostoa jonossa","File: %s, size: %d, max file size: %d":"Tiedosto: %s, koko: %d, suurin sallittu tiedostokoko: %d","Drag files here.":"Raahaa tiedostot tähän.","Runtime ran out of available memory.":"Toiminnon käytettävissä oleva muisti loppui kesken.","File count error.":"Tiedostolaskentavirhe.","File extension error.":"Tiedostopäätevirhe.","Error: File too large:":"Virhe: Liian suuri tiedosto:","Add Files":"Lisää tiedostoja"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// French (fr)
|
||||
plupload.addI18n({"Stop Upload":"Arrêter l'envoi.","Upload URL might be wrong or doesn't exist.":"L'URL d'envoi est soit erronée soit n'existe pas.","tb":"To","Size":"Taille","Close":"Fermer","Init error.":"Erreur d'initialisation.","Add files to the upload queue and click the start button.":"Ajoutez des fichiers à la file d'attente de téléchargement et appuyez sur le bouton 'Démarrer l'envoi'","Filename":"Nom du fichier","Image format either wrong or not supported.":"Le format d'image est soit erroné soit pas géré.","Status":"État","HTTP Error.":"Erreur HTTP.","Start Upload":"Démarrer l'envoi","mb":"Mo","kb":"Ko","Duplicate file error.":"Erreur: Fichier déjà sélectionné.","File size error.":"Erreur de taille de fichier.","N/A":"Non applicable","gb":"Go","Error: Invalid file extension:":"Erreur: Extension de fichier non valide:","Select files":"Sélectionnez les fichiers","%s already present in the queue.":"%s déjà présent dans la file d'attente.","File: %s":"Fichier: %s","b":"o","Uploaded %d/%d files":"%d fichiers sur %d ont été envoyés","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Que %d fichier(s) peuvent être envoyé(s) à la fois. Les fichiers supplémentaires ont été ignorés.","%d files queued":"%d fichiers en attente","File: %s, size: %d, max file size: %d":"Fichier: %s, taille: %d, taille max. d'un fichier: %d","Drag files here.":"Déposez les fichiers ici.","Runtime ran out of available memory.":"Le traitement a manqué de mémoire disponible.","File count error.":"Erreur: Nombre de fichiers.","File extension error.":"Erreur d'extension de fichier","Error: File too large:":"Erreur: Fichier trop volumineux:","Add Files":"Ajouter des fichiers"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Hebrew (he)
|
||||
plupload.addI18n({"Stop Upload":"בטל העלאה","Upload URL might be wrong or doesn't exist.":"כתובת URL שגויה או לא קיימת.","tb":"tb","Size":"גודל","Close":"סגור","Init error.":"שגיאת איתחול","Add files to the upload queue and click the start button.":"הוסף קבצים לרשימה ולחץ על כפתור שליחה להתחלת פעולות העלאה","Filename":"שם קובץ","Image format either wrong or not supported.":"תמונה פגומה או סוג תמונה לא נתמך","Status":"אחוז","HTTP Error.":"שגיאת פרוטוקול","Start Upload":"שליחה","mb":"MB","kb":"KB","Duplicate file error.":"קובץ כפול","File size error.":"גודל קובץ חורג מהמותר","N/A":"שגיאה","gb":"GB","Error: Invalid file extension:":"שגיאה: סוג קובץ לא נתמך:","Select files":"בחר קבצים","%s already present in the queue.":"%sקובץ נמצא כבר ברשימת הקבצים.","File: %s":"קובץ: %s","b":"B","Uploaded %d/%d files":"מעלה: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"אלמנטי ההעלאה מקבלים רק %d קובץ(ים) בפעם אחת. קבצים נוספים הוסרו.","%d files queued":"%d קבצים נותרו","File: %s, size: %d, max file size: %d":"קובץ: %s, גודל: %d, גודל מקסימלי: %d","Drag files here.":"גרור קבצים לכאן","Runtime ran out of available memory.":"שגיאת מחסור בזיכרון","File count error.":"שגיאת מספר קבצים","File extension error.":"קובץ זה לא נתמך","Error: File too large:":"שגיאה: קובץ חורג מהגודל המותר:","Add Files":"הוסף קבצים"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Croatian (hr)
|
||||
plupload.addI18n({"Stop Upload":"Zaustavi upload.","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Veličina","Close":"Zatvori","Init error.":"Greška inicijalizacije.","Add files to the upload queue and click the start button.":"Dodajte datoteke u listu i kliknite Upload.","Filename":"Ime datoteke","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP greška.","Start Upload":"Pokreni upload.","mb":"mb","kb":"kb","Duplicate file error.":"Pogreška dvostruke datoteke.","File size error.":"Greška veličine datoteke.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Pogreška: Nevažeći nastavak datoteke:","Select files":"Odaberite datoteke:","%s already present in the queue.":"%s je već prisutan u listi čekanja.","File: %s":"Datoteka: %s","b":"b","Uploaded %d/%d files":"Uploadano %d/%d datoteka","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d datoteka na čekanju.","File: %s, size: %d, max file size: %d":"Datoteka: %s, veličina: %d, maksimalna veličina: %d","Drag files here.":"Dovucite datoteke ovdje","Runtime ran out of available memory.":"Runtime aplikaciji je ponestalo memorije.","File count error.":"Pogreška u broju datoteka.","File extension error.":"Pogreška u nastavku datoteke.","Error: File too large:":"Pogreška: Datoteka je prevelika:","Add Files":"Dodaj datoteke"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Hungarian (hu)
|
||||
plupload.addI18n({"Stop Upload":"Feltöltés leállítása","Upload URL might be wrong or doesn't exist.":"A feltöltő URL hibás vagy nem létezik.","tb":"TB","Size":"Méret","Close":"Bezárás","Init error.":"Init hiba.","Add files to the upload queue and click the start button.":"A fájlok feltöltési sorhoz való hozzáadása után az Indítás gombra kell kattintani.","Filename":"Fájlnév","Image format either wrong or not supported.":"Rossz vagy nem támogatott képformátum.","Status":"Állapot","HTTP Error.":"HTTP-hiba.","Start Upload":"Feltöltés indítása","mb":"MB","kb":"kB","Duplicate file error.":"Duplikáltfájl-hiba.","File size error.":"Hibás fájlméret.","N/A":"Nem elérhető","gb":"GB","Error: Invalid file extension:":"Hiba: érvénytelen fájlkiterjesztés:","Select files":"Fájlok kiválasztása","%s already present in the queue.":"%s már szerepel a listában.","File: %s":"Fájl: %s","b":"b","Uploaded %d/%d files":"Feltöltött fájlok: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"A feltöltés egyszerre csak %d fájlt fogad el, a többi fájl nem lesz feltöltve.","%d files queued":"%d fájl sorbaállítva","File: %s, size: %d, max file size: %d":"Fájl: %s, méret: %d, legnagyobb fájlméret: %d","Drag files here.":"Ide lehet húzni a fájlokat.","Runtime ran out of available memory.":"Futásidőben elfogyott a rendelkezésre álló memória.","File count error.":"A fájlok számával kapcsolatos hiba.","File extension error.":"Hibás fájlkiterjesztés.","Error: File too large:":"Hiba: a fájl túl nagy:","Add Files":"Fájlok hozzáadása"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Armenian (hy)
|
||||
plupload.addI18n({"Stop Upload":"Կանգնեցնել","Upload URL might be wrong or doesn't exist.":"Ավեցաված URL-ը սխալ է կամ գոյություն չունի։","tb":"տբ","Size":"Չափ","Close":"Փակել","Init error.":"Ստեղծման սխալ","Add files to the upload queue and click the start button.":"Ավելացրեք ֆայլեր ցուցակում և սեղմեք \"Վերբեռնել\"։","Filename":"Ֆայլի անուն","Image format either wrong or not supported.":"Նկարի ֆորմատը սխալ է կամ չի ընդունվում։","Status":"Կարգավիճակ","HTTP Error.":"HTTP սխալ","Start Upload":"Վերբեռնել","mb":"մբ","kb":"կբ","Duplicate file error.":"Ֆայլի կրկնման սխալ","File size error.":"Ֆայլի չափի սխալ","N/A":"N/A","gb":"գբ","Error: Invalid file extension:":"Սխալ։ Ֆայլի ընդլայնումը սխալ է։","Select files":"Ընտրեք ֆայլերը","%s already present in the queue.":"%s ֆայլը արդեն ավելացված է ցուցակում.","File: %s":"Ֆայլ: %s","b":"բ","Uploaded %d/%d files":"Վերբեռնվել են %d/%d ֆայլերը","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Վերբեռնիչը միանգամից ըդունում է միայն %d ֆայլ(եր). Ավելորդ ֆայլերը հեռացվել են.","%d files queued":"ցուցակում կա %d ֆայլ","File: %s, size: %d, max file size: %d":"Ֆայլ: %s, չափ: %d, ֆայլի մաքսիմում չափ: %d","Drag files here.":"Տեղափոխեք ֆայլերը այստեղ","Runtime ran out of available memory.":"Օպերատիվ հիշողության անբավարարուտյուն.","File count error.":"Ֆայլերի քանակի սխալ","File extension error.":"Ֆայլի ընդլայնման սխալ","Error: File too large:":"Սխալ։ Ֆայլի չափը մեծ է։","Add Files":"Ավելացնել ֆայլեր"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Indonesian (id)
|
||||
plupload.addI18n({"Stop Upload":"Hentikan Upload","Upload URL might be wrong or doesn't exist.":"Alamat URL untuk upload tidak benar atau tidak ada","tb":"tb","Size":"Ukuran","Close":"Tutup","Init error.":"Kesalahan pada Init","Add files to the upload queue and click the start button.":"Tambahkan file kedalam antrian upload dan klik tombol Mulai","Filename":"Nama File","Image format either wrong or not supported.":"Kesalahan pada jenis gambar atau jenis file tidak didukung","Status":"Status","HTTP Error.":"HTTP Bermasalah","Start Upload":"Mulai Upload","mb":"mb","kb":"kb","Duplicate file error.":"Terjadi duplikasi file","File size error.":"Kesalahan pada ukuran file","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Kesalahan: Ekstensi file tidak dikenal","Select files":"Pilih file","%s already present in the queue.":"%s sudah ada dalam daftar antrian","File: %s":"File: %s","b":"b","Uploaded %d/%d files":"File terupload %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Tempat untuk upload hanya menerima %d file(s) dalam setiap upload. File lainnya tidak akan disertakan","%d files queued":"%d file dalam antrian","File: %s, size: %d, max file size: %d":"File: %s, ukuran: %d, maksimum ukuran file: %d","Drag files here.":"Tarik file kesini","Runtime ran out of available memory.":"Tidak cukup memori","File count error.":"Kesalahan pada jumlah file","File extension error.":"Kesalahan pada ekstensi file","Error: File too large:":"Kesalahan: File terlalu besar","Add Files":"Tambah File"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Italian (it)
|
||||
plupload.addI18n({"Stop Upload":"Ferma Upload","Upload URL might be wrong or doesn't exist.":"URL di Upload errata o non esistente","tb":"tb","Size":"Dimensione","Close":"Chiudi","Init error.":"Errore inizializzazione.","Add files to the upload queue and click the start button.":"Aggiungi i file alla coda di caricamento e clicca il pulsante di avvio.","Filename":"Nome file","Image format either wrong or not supported.":"Formato immagine errato o non supportato.","Status":"Stato","HTTP Error.":"Errore HTTP.","Start Upload":"Inizia Upload","mb":"mb","kb":"kb","Duplicate file error.":"Errore file duplicato.","File size error.":"Errore dimensione file.","N/A":"N/D","gb":"gb","Error: Invalid file extension:":"Errore: Estensione file non valida:","Select files":"Seleziona i files","%s already present in the queue.":"%s già presente nella coda.","File: %s":"File: %s","b":"byte","Uploaded %d/%d files":"Caricati %d/%d file","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d file in coda","File: %s, size: %d, max file size: %d":"File: %s, dimensione: %d, dimensione max file: %d","Drag files here.":"Trascina i files qui.","Runtime ran out of available memory.":"Runtime ha esaurito la memoria disponibile.","File count error.":"File count error.","File extension error.":"Errore estensione file.","Error: File too large:":"Errore: File troppo grande:","Add Files":"Aggiungi file"});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Japanese (ja)
|
||||
plupload.addI18n({"Stop Upload":"アップロード停止","Upload URL might be wrong or doesn't exist.":"アップロード先の URL が存在しません","tb":"TB","Size":"サイズ","Close":"閉じる","Init error.":"イニシャライズエラー","Add files to the upload queue and click the start button.":"ファイルをアップロードキューに追加してスタートボタンをクリックしてください","Filename":"ファイル名","Image format either wrong or not supported.":"画像形式が間違っているかサポートされていません","Status":"ステータス","HTTP Error.":"HTTP エラー","Start Upload":"アップロード開始","mb":"MB","kb":"KB","Duplicate file error.":"重複ファイルエラー","File size error.":"ファイルサイズエラー","N/A":"N/A","gb":"GB","Error: Invalid file extension:":"エラー: ファイルの拡張子が無効です:","Select files":"ファイル選択","%s already present in the queue.":"%s 既にキューに存在しています","File: %s":"ファイル: %s","b":"B","Uploaded %d/%d files":"アップロード中 %d/%d ファイル","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"アップロード可能なファイル数は %d です 余分なファイルは削除されました","%d files queued":"%d ファイルが追加されました","File: %s, size: %d, max file size: %d":"ファイル: %s, サイズ: %d, 最大ファイルサイズ: %d","Drag files here.":"ここにファイルをドラッグ","Runtime ran out of available memory.":"ランタイムが使用するメモリが不足しました","File count error.":"ファイル数エラー","File extension error.":"ファイル拡張子エラー","Error: File too large:":"エラー: ファイルが大きすぎます:","Add Files":"ファイルを追加"});
|
||||