|
@ -0,0 +1,2 @@
|
|||
bin/
|
||||
obj/
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: test-build
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: sed-tgt-version
|
||||
pull: always
|
||||
image: bash
|
||||
commands:
|
||||
- sed -i 's/3.1.110/3.1.404/' global.json
|
||||
# since we're running 3.1.404 here in the CI, this is necessary
|
||||
|
||||
- name: debug
|
||||
pull: always
|
||||
image: mcr.microsoft.com/dotnet/core/sdk:3.1-alpine
|
||||
depends_on:
|
||||
- sed-tgt-version
|
||||
commands:
|
||||
- dotnet restore
|
||||
- dotnet build .
|
||||
|
||||
- name: release
|
||||
pull: always
|
||||
image: mcr.microsoft.com/dotnet/core/sdk:3.1-alpine
|
||||
depends_on:
|
||||
- sed-tgt-version
|
||||
commands:
|
||||
- dotnet restore
|
||||
- dotnet publish -c Release -o out
|
||||
|
||||
- name: docker-release-build
|
||||
pull: always
|
||||
image: ghcr.io/finitum/drone-kaniko:0.7.0
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
context: .
|
||||
|
||||
- name: docker-debug-build
|
||||
pull: always
|
||||
image: ghcr.io/finitum/drone-kaniko:0.7.0
|
||||
settings:
|
||||
dockerfile: Dockerfile.dev
|
||||
context: .
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
bin/
|
||||
obj/
|
||||
/packages/
|
||||
riderModule.iml
|
||||
/_ReSharper.Caches/
|
||||
*.swp
|
|
@ -0,0 +1,105 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using pwt_final_countdown.Models;
|
||||
using pwt_final_countdown.Models.Dbfake;
|
||||
|
||||
namespace pwt_final_countdown.Areas.PCKomponenty.Controllers
|
||||
{
|
||||
[Area("PCKomponenty")]
|
||||
public class ProcessorController : Controller
|
||||
{
|
||||
IWebHostEnvironment hosting_env;
|
||||
private IList<Processor> Processors = Dbfake.Processors;
|
||||
|
||||
public ProcessorController(IWebHostEnvironment hosting_env){
|
||||
this.hosting_env = hosting_env;
|
||||
}
|
||||
|
||||
public IActionResult All()
|
||||
{
|
||||
ProcessorViewModel processor = new ProcessorViewModel();
|
||||
processor.Processors = Processors;
|
||||
return View(processor);
|
||||
}
|
||||
|
||||
// GET
|
||||
public IActionResult Select()
|
||||
{
|
||||
ProcessorViewModel processor = new ProcessorViewModel();
|
||||
processor.Processors = Processors;
|
||||
return View(processor);
|
||||
}
|
||||
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create(Processor processor)
|
||||
{
|
||||
processor.ImageSrc = string.Empty;
|
||||
MegaUpload mega_upload = new MegaUpload(hosting_env);
|
||||
await mega_upload.DoMegaUpload(processor);
|
||||
|
||||
Processors.Add(processor);
|
||||
return RedirectToAction(nameof(Select));
|
||||
}
|
||||
|
||||
public IActionResult Edit(int id)
|
||||
{
|
||||
Processor processor_item = Processors.Where(p_item => p_item.id == id).FirstOrDefault();
|
||||
if (processor_item != null)
|
||||
{
|
||||
return View(processor_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Edit(Processor processor)
|
||||
{
|
||||
Processor processor_item = Processors.Where(p_item => p_item.id == processor.id).FirstOrDefault();
|
||||
|
||||
if (processor_item != null)
|
||||
{
|
||||
processor_item.id = processor.id;
|
||||
processor_item.DataTarget = processor.DataTarget;
|
||||
processor_item.ImageAlt = processor.ImageAlt;
|
||||
processor_item.Description = processor.Description;
|
||||
|
||||
MegaUpload mega_upload = new MegaUpload(hosting_env);
|
||||
if (await mega_upload.DoMegaUpload(processor)){
|
||||
processor_item.ImageSrc = processor.ImageSrc;
|
||||
}
|
||||
return RedirectToAction(nameof(Select));
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
public IActionResult Delete(int id)
|
||||
{
|
||||
Processor processor_item = Processors.Where(p_item => p_item.id == id).FirstOrDefault();
|
||||
if (processor_item != null)
|
||||
{
|
||||
Processors.Remove(processor_item);
|
||||
return RedirectToAction(nameof(Select));
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
@model ProcessorViewModel
|
||||
@{
|
||||
ViewData["Title"] = "All processors view";
|
||||
}
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
<h3>@ViewData["Message"]</h3>
|
||||
|
||||
<p>View all processors</p>
|
||||
<br/>
|
||||
|
||||
@{
|
||||
if (Model?.Processors != null && Model.Processors.Count > 0) {
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<th class="col-sm-1">@Html.DisplayNameFor(model => model.Processors[0].id)</th>
|
||||
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Processors[0].name)</th>
|
||||
<th class="col-sm-4">@Html.DisplayNameFor(model => model.Processors[0].Description)</th>
|
||||
<th class="col-lg-4">Image</th>
|
||||
|
||||
</tr>
|
||||
@{
|
||||
foreach (var processor_item in Model.Processors)
|
||||
{
|
||||
<tr>
|
||||
<td class="col-sm-1">@processor_item.id</td>
|
||||
<td class="col-sm-2">@processor_item.name</td>
|
||||
<td class="col-sm-4">@processor_item.Description</td>
|
||||
<td class="col-lg-4"><img src="@processor_item.ImageSrc" style="max-height:200px;max-width:500px;width: expression(this.width > 500 ? 500: true);"/></td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</table>
|
||||
}
|
||||
else
|
||||
{
|
||||
<h2>Processor view is empty</h2>
|
||||
}
|
||||
}
|
||||
|
||||
@section Scripts
|
||||
{
|
||||
<script src="~/js/ultimate_script.js"></script>
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
@model Processor
|
||||
@{
|
||||
ViewData["Title"] = "Processor Creation";
|
||||
}
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
<h3>@ViewData["Message"]</h3>
|
||||
|
||||
<p>Add new processor item.</p>
|
||||
|
||||
@{ViewBag.Action = "Create";}
|
||||
@await Html.PartialAsync("PartialForm_EditCreate", Model)
|
|
@ -0,0 +1,11 @@
|
|||
@model Processor
|
||||
@{
|
||||
ViewData["Title"] = "Processor Editing";
|
||||
}
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
<h3>@ViewData["Message"]</h3>
|
||||
|
||||
<p>Edit processor item.</p>
|
||||
|
||||
@{ViewBag.Action = "Edit";}
|
||||
<partial name="PartialForm_EditCreate" model="Model">
|
|
@ -0,0 +1,60 @@
|
|||
@model Processor
|
||||
@{
|
||||
if((!String.IsNullOrEmpty(ViewBag.Action))||(!String.IsNullOrWhiteSpace(ViewBag.Action)))
|
||||
{
|
||||
<div class="row">
|
||||
<form asp-action="@ViewBag.Action" enctype="multipart/form-data" method="post">
|
||||
<div class="form-group col-sm-4">
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.id"></label>
|
||||
<input asp-for="@Model.id" class="form-control" id="inputp" aria-describedby="help" placeholder="id">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.DataTarget"></label>
|
||||
<input asp-for="@Model.DataTarget" class="form-control" id="inputp" aria-describedby="css selector id of the image" placeholder="Data Target">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.name"></label>
|
||||
<input asp-for="@Model.name" class="form-control" id="inputp" placeholder="name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.clock_speed"></label>
|
||||
<input asp-for="@Model.clock_speed" class="form-control" id="inputp" placeholder="name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.generation"></label>
|
||||
<input asp-for="@Model.generation" class="form-control" id="inputp" placeholder="generation">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.socket"></label>
|
||||
<input asp-for="@Model.socket" class="form-control" id="inputp" placeholder="socket">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.cores"></label>
|
||||
<input asp-for="@Model.cores" class="form-control" id="inputp" placeholder="cores">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.price"></label>
|
||||
<input asp-for="@Model.price" class="form-control" id="inputp" placeholder="price">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.Image"></label>
|
||||
<input asp-for="@Model.Image" accept="image/*" class="form-inline" id="inputp" aria-describedby="the image">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.ImageAlt"></label>
|
||||
<input asp-for="@Model.ImageAlt" class="form-control" id="inputp" aria-describedby="image alt text" placeholder="Image alt">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.Description"></label>
|
||||
<input asp-for="@Model.Description" class="form-control" id="inputp" aria-describedby="image description" placeholder="Image description">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
else {
|
||||
<h2>Error: Action is not set</h2>
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
@model ProcessorViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Processor Select";
|
||||
}
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
<h3>@ViewData["Message"]</h3>
|
||||
|
||||
<p>Select all data from processor.</p>
|
||||
<br/>
|
||||
<a asp-action="All">View all</a>
|
||||
<br/><br/>
|
||||
<a asp-action="Create">Create new processor item</a>
|
||||
<br/><br/>
|
||||
<br/>
|
||||
|
||||
@{
|
||||
if (Model?.Processors != null && Model.Processors.Count > 0) {
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<th class="col-sm-1">@Html.DisplayNameFor(model => model.Processors[0].id)</th>
|
||||
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Processors[0].name)</th>
|
||||
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Processors[0].generation)</th>
|
||||
<th class="col-sm-1">@Html.DisplayNameFor(model => model.Processors[0].clock_speed)</th>
|
||||
<th class="col-sm-1">@Html.DisplayNameFor(model => model.Processors[0].cores)</th>
|
||||
<th class="col-sm-1">@Html.DisplayNameFor(model => model.Processors[0].price)</th>
|
||||
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Processors[0].ImageSrc)</th>
|
||||
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Processors[0].ImageAlt)</th>
|
||||
<th class="col-sm-4">@Html.DisplayNameFor(model => model.Processors[0].Description)</th>
|
||||
<th class="col-sm-1">Edit</th>
|
||||
<th class="col-sm-1">Delete</th>
|
||||
</tr>
|
||||
@{
|
||||
foreach (var processor_item in Model.Processors)
|
||||
{
|
||||
<tr>
|
||||
<td class="col-sm-1">@processor_item.id</td>
|
||||
<td class="col-sm-2">@processor_item.name</td>
|
||||
<td class="col-sm-2">@processor_item.generation</td>
|
||||
<td class="col-sm-1">@processor_item.clock_speed</td>
|
||||
<td class="col-sm-1">@processor_item.cores</td>
|
||||
<td class="col-sm-1">@processor_item.price</td>
|
||||
<td class="col-sm-2">@processor_item.ImageSrc</td>
|
||||
<td class="col-sm-2">@processor_item.ImageAlt</td>
|
||||
<td class="col-sm-4">@processor_item.Description</td>
|
||||
<td class="col-sm-2"><a asp-action="Edit" asp-route-id="@processor_item.id">Edit</a></td>
|
||||
<td class="col-sm-2"><a asp-action="Delete" asp-route-id="@processor_item.id" onclick="return p_item_deletion_confirmation();">Delete</a></td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</table>
|
||||
}
|
||||
else
|
||||
{
|
||||
<h2>Carousel is empty</h2>
|
||||
}
|
||||
}
|
||||
|
||||
@section Scripts
|
||||
{
|
||||
<script src="~/js/ultimate_script.js"></script>
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
@using pwt_final_countdown
|
||||
@using pwt_final_countdown.Models
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using pwt_final_countdown.Models;
|
||||
using pwt_final_countdown.Models.Dbfake;
|
||||
|
||||
namespace pwt_final_countdown.Controllers
|
||||
{
|
||||
public class HomeController : Controller
|
||||
{
|
||||
private IList<Processor> Processors = Dbfake.Processors;
|
||||
|
||||
public IActionResult Index()
|
||||
{
|
||||
ProcessorViewModel processor = new ProcessorViewModel();
|
||||
processor.Processors = Processors;
|
||||
return View(processor);
|
||||
}
|
||||
|
||||
public IActionResult About()
|
||||
{
|
||||
ViewData["Message"] = "About this awesome app.";
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Contact()
|
||||
{
|
||||
ViewData["Message"] = "Your contact page.";
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Privacy()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine
|
||||
ENV UID 1000
|
||||
ENV GID 1000
|
||||
ENV UNAME unpriv
|
||||
RUN adduser -D -u ${UID} -g ${GID} -H ${UNAME} -h /src
|
||||
WORKDIR /src
|
||||
|
||||
COPY global.json ./
|
||||
RUN sed -i 's/3.1.110/3.1.404/' global.json
|
||||
|
||||
COPY *.csproj ./
|
||||
RUN dotnet restore
|
||||
|
||||
COPY . ./
|
||||
RUN sed -i 's/3.1.110/3.1.404/' global.json
|
||||
RUN dotnet publish -c Release -o bin/out
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:3.1
|
||||
WORKDIR /App
|
||||
COPY --from=0 /src/bin/out/ .
|
||||
RUN chown -R ${UID}:${GID} ./
|
||||
USER ${UNAME}
|
||||
ENV ASPNETCORE_ENVIRONMENT=Release
|
||||
ENTRYPOINT ["dotnet", "pwt-0x01-ng.dll"]
|
|
@ -0,0 +1,22 @@
|
|||
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine
|
||||
ENV UID 1000
|
||||
ENV GID 1000
|
||||
ENV UNAME unpriv
|
||||
RUN adduser -D -u ${UID} -g ${GID} -H ${UNAME} -h /src
|
||||
WORKDIR /src
|
||||
|
||||
COPY global.json ./
|
||||
RUN sed -i 's/3.1.110/3.1.404/' global.json
|
||||
|
||||
COPY *.csproj ./
|
||||
RUN dotnet restore
|
||||
|
||||
COPY . ./
|
||||
RUN sed -i 's/3.1.110/3.1.404/' global.json
|
||||
RUN dotnet build -c Debug -o bin/out
|
||||
RUN chown -R ${UID}:${GID} ./ /root/
|
||||
USER ${UNAME}
|
||||
|
||||
ENV ASPNETCORE_ENVIRONMENT=Development
|
||||
|
||||
ENTRYPOINT ["dotnet", "watch", "run", "--no-restore", "--urls", "http://0.0.0.0:5000"]
|
|
@ -0,0 +1,13 @@
|
|||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
|
@ -0,0 +1,78 @@
|
|||
dtag = netcorezapocet
|
||||
dtagdev = netcorezapocet-dev
|
||||
dfile = Dockerfile
|
||||
dfiledev = $(dfile).dev
|
||||
lport = 8000
|
||||
lportdev = 8001
|
||||
CC = dotnet
|
||||
dcmd = docker
|
||||
pruneargs = system prune -af
|
||||
dcmdrun = $(dcmd) run --rm
|
||||
wdir = /src
|
||||
kanikoimg = gcr.io/kaniko-project/executor
|
||||
dargskaniko = -w=$(wdir) -v $$(pwd):$(wdir) $(kanikoimg)
|
||||
kanikoargs = -c=$(wdir) --use-new-run --snapshotMode=redo --no-push
|
||||
krelease = $(dcmdrun) $(dargskaniko) -f=$(dfile) $(kanikoargs)
|
||||
kdebug = $(dcmdrun) $(dargskaniko) -f=$(dfiledev) $(kanikoargs)
|
||||
|
||||
.PHONY: dev dockerbuild dockerdevbuild dockerrun dockerdevrun dockertest dockerdev kaniko clean prune test
|
||||
|
||||
dev: restore build run
|
||||
|
||||
restore:
|
||||
$(CC) restore
|
||||
|
||||
build:
|
||||
$(CC) build .
|
||||
|
||||
run:
|
||||
$(CC) watch run . --no-restore
|
||||
|
||||
releasebuild: restore clean
|
||||
$(CC) publish -c Release
|
||||
|
||||
dockerbuild:
|
||||
docker build \
|
||||
--build-arg VCS_REF=`git rev-parse --short HEAD` \
|
||||
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
|
||||
-t $(dtag) -f $(dfile) .
|
||||
|
||||
dockerdevbuild:
|
||||
docker build \
|
||||
--build-arg VCS_REF=`git rev-parse --short HEAD` \
|
||||
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
|
||||
-t $(dtagdev) -f $(dfiledev) .
|
||||
|
||||
dockerrun:
|
||||
@echo ======================
|
||||
@echo local port: $(lport)
|
||||
@echo ======================
|
||||
$(dcmdrun) -p $(lport):80 $(dtag)
|
||||
|
||||
dockerdevrun:
|
||||
@echo ======================
|
||||
@echo local dev port: $(lportdev)
|
||||
@echo ======================
|
||||
$(dcmdrun) -p $(lportdev):5000 $(dtagdev)
|
||||
|
||||
dcdevrun:
|
||||
@echo ======================
|
||||
@echo local dev port: $(lportdev)
|
||||
@echo ======================
|
||||
docker-compose up --build --remove-orphans
|
||||
|
||||
kaniko:
|
||||
$(krelease)
|
||||
$(kdebug)
|
||||
|
||||
dockerdev: dockerdevbuild dockerdevrun
|
||||
|
||||
dockertest: dockerdevbuild dockerbuild
|
||||
|
||||
test: releasebuild build dockertest kaniko
|
||||
|
||||
clean:
|
||||
$(CC) clean
|
||||
|
||||
prune:
|
||||
$(dcmd) $(pruneargs)
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace pwt_final_countdown.Models.Dbfake
|
||||
{
|
||||
public static class Dbfake
|
||||
{
|
||||
/* singe db table simulation*/
|
||||
public static IList<Processor> Processors { get; set; }
|
||||
|
||||
static Dbfake()
|
||||
{
|
||||
Processors = ProcessorHelper.GenerateProcessors();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace pwt_final_countdown.Models.Dbfake
|
||||
{
|
||||
public static class ProcessorHelper
|
||||
{
|
||||
public static IList<Processor> GenerateProcessors()
|
||||
{
|
||||
IList<Processor> processors = new List<Processor>()
|
||||
{
|
||||
new Processor() { id = 0, name = "whatever", clock_speed=5, socket="SOMELGA", cores=256, generation=1, price=9001, DataTarget = "#myCarousel", ImageSrc = "/images/banner1.svg", ImageAlt = "ASP.NET", Description = "Learn how to build ASP.NET apps that can run anywhere.<a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkID=525028&clcid=0x409\">Learn More</a>"},
|
||||
new Processor() { id = 1, name = "whatever", clock_speed=5, socket="SOMELGA", cores=256, generation=1, price=9001, DataTarget = "#myCarousel", ImageSrc = "/images/banner2.svg", ImageAlt = "ASP.NET", Description = "There are powerful new features in Visual Studio for building modern web apps.<a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkID=525030&clcid=0x409\">Learn More</a>"},
|
||||
new Processor() { id = 2, name = "whatever", clock_speed=5, socket="SOMELGA", cores=256, generation=1, price=9001, DataTarget = "#myCarousel", ImageSrc = "/images/banner3.svg", ImageAlt = "ASP.NET", Description = "Learn how Microsoft's Azure cloud platform allows you to build, deploy, and scale web apps.<a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkID=525027&clcid=0x409\">Learn More</a>"},
|
||||
new Processor() { id = 3, name = "whatever", clock_speed=5, socket="SOMELGA", cores=256, generation=1, price=9001, DataTarget = "#myCarousel", ImageSrc = "/images/ms_loves_linux.jpeg", ImageAlt = "msloveslinux", Description = "ms loves linux"}
|
||||
};
|
||||
return processors;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
|
||||
namespace pwt_final_countdown.Models
|
||||
{
|
||||
public class ErrorViewModel
|
||||
{
|
||||
public string RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace pwt_final_countdown.Models
|
||||
{
|
||||
public class MegaUpload
|
||||
{
|
||||
IWebHostEnvironment hosting_env;
|
||||
|
||||
public MegaUpload(IWebHostEnvironment hosting_env){
|
||||
this.hosting_env = hosting_env;
|
||||
}
|
||||
public async Task<bool> DoMegaUpload(Processor processor)
|
||||
{
|
||||
bool great_success = false;
|
||||
var img = processor.Image;
|
||||
if(img != null && img.ContentType.ToLower().Contains("image") && img.Length > 0 && img.Length < 2000000){
|
||||
var fname = Path.GetFileNameWithoutExtension(img.FileName);
|
||||
var fext = Path.GetExtension(img.FileName);
|
||||
/* in case such file already exists - wip */
|
||||
/* var fname_rand = Path.GetRandomFileName()+Path.GetFileNameWithoutExtension(img.FileName); */
|
||||
var f_relative = Path.Combine("images","processors", fname + fext);
|
||||
var file_path = Path.Combine(hosting_env.WebRootPath, f_relative);
|
||||
|
||||
using (var stream = new FileStream(file_path, FileMode.Create)){
|
||||
await img.CopyToAsync(stream);
|
||||
}
|
||||
processor.ImageSrc = $"/{f_relative}";
|
||||
great_success = true;
|
||||
}
|
||||
return great_success;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace pwt_final_countdown.Models
|
||||
{
|
||||
public class Processor
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string name { get; set; }
|
||||
public int clock_speed { get; set; }
|
||||
public string socket { get; set; }
|
||||
public int cores { get; set; }
|
||||
public int generation { get; set; }
|
||||
public int price { get; set; }
|
||||
public string DataTarget { get; set; }
|
||||
public IFormFile Image { get; set; }
|
||||
public string ImageSrc { get; set; }
|
||||
public string ImageAlt { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace pwt_final_countdown.Models
|
||||
{
|
||||
public class ProcessorViewModel
|
||||
{
|
||||
public IList<Processor> Processors { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace pwt_final_countdown
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"profiles": {
|
||||
"pwt_0x01_ng": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
# pwt-final-countdown
|
||||
|
||||
this repo holds *sawce* for PWT .netcore mvc project final-countdown
|
||||
|
||||
### how to run this
|
||||
> run the following commands from the solution folder
|
||||
|
||||
on the first run, restore stuff
|
||||
```sh
|
||||
dotnet restore
|
||||
```
|
||||
|
||||
build and run
|
||||
```sh
|
||||
dotnet build && dotnet run
|
||||
```
|
||||
#### errors
|
||||
if you get a weird long error about not being able to listen bind a port, make sure nothing else is listening on the port *this* thing is trying to bind (tcp/5000).
|
||||
if something else *is* already listening, solve it by killing it before running `dotnet run` or change the app port in [[Properties/launchSettings.json]]
|
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.CookiePolicy;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace pwt_final_countdown
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<CookiePolicyOptions>(options =>
|
||||
{
|
||||
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
|
||||
options.CheckConsentNeeded = context => true;
|
||||
options.MinimumSameSitePolicy = SameSiteMode.Lax;
|
||||
options.HttpOnly = HttpOnlyPolicy.Always;
|
||||
options.Secure = CookieSecurePolicy.Always;
|
||||
});
|
||||
services.Configure<MvcOptions>(options => {
|
||||
/* necessary due to a switch to 3.1 */
|
||||
options.EnableEndpointRouting = false;
|
||||
});
|
||||
|
||||
|
||||
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.EnvironmentName.Equals("Development"))
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseExceptionHandler("/Home/Error");
|
||||
}
|
||||
|
||||
app.UseStaticFiles();
|
||||
app.UseCookiePolicy();
|
||||
|
||||
app.UseMvc(routes =>
|
||||
{
|
||||
routes.MapRoute(
|
||||
name: "areas",
|
||||
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
|
||||
);
|
||||
routes.MapRoute(
|
||||
name: "default",
|
||||
template: "{controller=Home}/{action=Index}/{id?}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
@{
|
||||
ViewData["Title"] = "About";
|
||||
}
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
<h3>@ViewData["Message"]</h3>
|
||||
|
||||
<p>pwt final countdown app</p>
|
|
@ -0,0 +1,9 @@
|
|||
@{
|
||||
ViewData["Title"] = "Contact";
|
||||
}
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
<h3>@ViewData["Message"]</h3>
|
||||
|
||||
<address>
|
||||
<strong>Support:</strong> <a href="mailto:a_mirre@utb.czm">pls click me</a><br/>
|
||||
</address>
|
|
@ -0,0 +1,86 @@
|
|||
@model ProcessorViewModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Home Page";
|
||||
}
|
||||
@section Styles {
|
||||
<link rel="stylesheet" href="~/css/Stylezbro.css"/>
|
||||
}
|
||||
|
||||
@{
|
||||
if (Model != null && Model.Processors.Count > 0)
|
||||
{
|
||||
<div id="@Model.Processors[0].DataTarget.Substring(1, Model.Processors[0].DataTarget.Length - 1)" class="carousel slide" data-ride="carousel" data-interval="6000">
|
||||
<ol class="carousel-indicators">
|
||||
@{
|
||||
for (int i = 0; i < Model.Processors.Count; i++)
|
||||
{
|
||||
string classli = String.Empty;
|
||||
if (i == 0)
|
||||
{
|
||||
classli = "class=\"active\"";
|
||||
}
|
||||
<li data-target="@Model.Processors[i].DataTarget" data-slide-to="@i" @Html.Raw(classli)></li>
|
||||
}
|
||||
}
|
||||
</ol>
|
||||
<div class="carousel-inner " role="listbox">
|
||||
@{
|
||||
for (int i = 0; i < Model.Processors.Count; i++)
|
||||
{
|
||||
string classitem = "item";
|
||||
if (i == 0)
|
||||
{
|
||||
classitem = "item active";
|
||||
}
|
||||
<div class="@classitem maxHeightCarousel">
|
||||
<img src="@Model.Processors[i].ImageSrc" alt="@Model.Processors[i].ImageAlt" class="img-responsive"/>
|
||||
<div class="carousel-caption" role="option">
|
||||
<p>
|
||||
@Html.Raw(Model.Processors[i].Description)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
|
||||
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
|
||||
<span class="sr-only">Previous</span>
|
||||
</a>
|
||||
<a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
|
||||
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
|
||||
<span class="sr-only">Next</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<h2>How to</h2>
|
||||
<ul>
|
||||
<li><a href="https://go.microsoft.com/fwlink/?LinkID=398600">Add a Controller and View</a></li>
|
||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699315">Manage User Secrets using Secret Manager.</a></li>
|
||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699316">Use logging to log a message.</a></li>
|
||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699317">Add packages using NuGet.</a></li>
|
||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699319">Target development, staging or production environment.</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<h2>Overview</h2>
|
||||
<ul>
|
||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=518008">Conceptual overview of what is ASP.NET Core</a></li>
|
||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699320">Fundamentals of ASP.NET Core such as Startup and middleware.</a></li>
|
||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=398602">Working with Data</a></li>
|
||||
<li><a href="https://go.microsoft.com/fwlink/?LinkId=398603">Security</a></li>
|
||||
<li><a href="https://go.microsoft.com/fwlink/?LinkID=699321">Client side development</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://go.microsoft.com/fwlink/?LinkID=699322">Develop on different platforms</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://go.microsoft.com/fwlink/?LinkID=699323">Read more on the documentation site</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
@{
|
||||
ViewData["Title"] = "Privacy Policy";
|
||||
}
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
|
||||
<p>We don't have any.</p>
|
|
@ -0,0 +1,22 @@
|
|||
@model ErrorViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Error";
|
||||
}
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (Model.ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
|
||||
</p>
|
|
@ -0,0 +1,43 @@
|
|||
@using Microsoft.AspNetCore.Http.Features
|
||||
|
||||
@{
|
||||
var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
|
||||
var showBanner = !consentFeature?.CanTrack ?? false;
|
||||
var cookieString = consentFeature?.CreateConsentCookie();
|
||||
}
|
||||
|
||||
@if (showBanner)
|
||||
{
|
||||
<nav id="cookieConsent" class="navbar navbar-default navbar-fixed-top" role="alert">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#cookieConsent .navbar-collapse">
|
||||
<span class="sr-only">Toggle cookie consent banner</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<span class="navbar-brand">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse">
|
||||
<p class="navbar-text">
|
||||
Use this space to summarize your privacy and cookie use policy.
|
||||
</p>
|
||||
<div class="navbar-right">
|
||||
<a asp-controller="Home" asp-action="Privacy" class="btn btn-info navbar-btn">Learn More</a>
|
||||
<button type="button" class="btn btn-default navbar-btn" data-cookie-string="@cookieString">Accept</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<script>
|
||||
(function () {
|
||||
document.querySelector("#cookieConsent button[data-cookie-string]").addEventListener("click", function (el) {
|
||||
document.cookie = el.target.dataset.cookieString;
|
||||
document.querySelector("#cookieConsent").classList.add("hidden");
|
||||
}, false);
|
||||
})();
|
||||
</script>
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>@ViewData["Title"] - pwt_final_countdown</title>
|
||||
|
||||
@RenderSection("Styles", required: false)
|
||||
<environment include="Development">
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css"/>
|
||||
<link rel="stylesheet" href="~/css/site.css"/>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
|
||||
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
|
||||
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"/>
|
||||
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true"/>
|
||||
</environment>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a asp-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">pwt_final_countdown</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li>
|
||||
<a asp-area="" asp-controller="Home" asp-action="Index">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a asp-area="" asp-controller="Home" asp-action="About">About</a>
|
||||
</li>
|
||||
<li>
|
||||
<a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a>
|
||||
</li>
|
||||
<li>
|
||||
<a asp-area="PCKomponenty" asp-controller="Processor" asp-action="Select">Processors</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<partial name="_CookieConsentPartial"/>
|
||||
|
||||
<div class="container body-content">
|
||||
@RenderBody()
|
||||
<hr/>
|
||||
<footer>
|
||||
<p>© 2020 - pwt_final_countdown</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<environment include="Development">
|
||||
<script src="~/lib/jquery/dist/jquery.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
|
||||
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
|
||||
asp-fallback-test="window.jQuery"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
|
||||
</script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"
|
||||
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd">
|
||||
</script>
|
||||
<script src="~/js/site.min.js" asp-append-version="true"></script>
|
||||
</environment>
|
||||
|
||||
@RenderSection("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<environment include="Development">
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.17.0/jquery.validate.min.js"
|
||||
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-rZfj/ogBloos6wzLGpPkkOr/gpkBNLZ6b6yLy4o+ok+t/SAKlL5mvXLr0OXNi1Hp">
|
||||
</script>
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.9/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-ifv0TYDWxBHzvAk2Z0n8R434FL1Rlv/Av18DXE43N/1rvHyOG4izKst0f2iSLdds">
|
||||
</script>
|
||||
</environment>
|
|
@ -0,0 +1,3 @@
|
|||
@using pwt_final_countdown
|
||||
@using pwt_final_countdown.Models
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
|
@ -0,0 +1,3 @@
|
|||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
netcorezapocetp-dev:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
ports:
|
||||
- 127.0.0.1:8001:5000
|
||||
volumes:
|
||||
- $PWD:/src
|
||||
environment:
|
||||
ASPNETCORE_ENVIRONMENT: Development
|
||||
restart: always
|
||||
cap_drop:
|
||||
- NET_ADMIN
|
||||
- SYS_ADMIN
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"sdk": {
|
||||
"version": "3.1.110"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFrameworks>netcoreapp3.1;</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Default' ">
|
||||
<StartAction>Project</StartAction>
|
||||
<LaunchBrowser>false</LaunchBrowser>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Areas\PCKomponenty\Data" />
|
||||
<Folder Include="Areas\PCKomponenty\Models" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pwt-final-countdown", "pwt-final-countdown.csproj", "{F08770D5-6E89-458A-BE85-BA945D0BB9DD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{F08770D5-6E89-458A-BE85-BA945D0BB9DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F08770D5-6E89-458A-BE85-BA945D0BB9DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F08770D5-6E89-458A-BE85-BA945D0BB9DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F08770D5-6E89-458A-BE85-BA945D0BB9DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,3 @@
|
|||
.maxHeightCarousel {
|
||||
max-height: 360px;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification\
|
||||
for details on configuring this project to bundle and minify static web assets. */
|
||||
body {
|
||||
padding-top: 50px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Wrapping element */
|
||||
/* Set some basic padding to keep content from hitting the edges */
|
||||
.body-content {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
/* Carousel */
|
||||
.carousel-caption p {
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Make .svg files in the carousel display properly in older browsers */
|
||||
.carousel-inner .item img[src$=".svg"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* QR code generator */
|
||||
#qrCode {
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
/* Hide/rearrange for smaller screens */
|
||||
@media screen and (max-width: 767px) {
|
||||
/* Hide captions */
|
||||
.carousel-caption {
|
||||
display: none;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}.carousel-caption p{font-size:20px;line-height:1.4}.carousel-inner .item img[src$=".svg"]{width:100%}#qrCode{margin:15px}@media screen and (max-width:767px){.carousel-caption{display:none}}
|
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 35 KiB |
|
@ -0,0 +1,4 @@
|
|||
// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
||||
// for details on configuring this project to bundle and minify static web assets.
|
||||
|
||||
// Write your JavaScript code.
|
|
@ -0,0 +1,3 @@
|
|||
function p_item_deletion_confirmation() {
|
||||
return confirm("Delete the item?");
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"name": "bootstrap",
|
||||
"description": "The most popular front-end framework for developing responsive, mobile first projects on the web.",
|
||||
"keywords": [
|
||||
"css",
|
||||
"js",
|
||||
"less",
|
||||
"mobile-first",
|
||||
"responsive",
|
||||
"front-end",
|
||||
"framework",
|
||||
"web"
|
||||
],
|
||||
"homepage": "http://getbootstrap.com",
|
||||
"license": "MIT",
|
||||
"moduleType": "globals",
|
||||
"main": [
|
||||
"less/bootstrap.less",
|
||||
"dist/js/bootstrap.js"
|
||||
],
|
||||
"ignore": [
|
||||
"/.*",
|
||||
"_config.yml",
|
||||
"CNAME",
|
||||
"composer.json",
|
||||
"CONTRIBUTING.md",
|
||||
"docs",
|
||||
"js/tests",
|
||||
"test-infra"
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": "1.9.1 - 3"
|
||||
},
|
||||
"version": "3.3.7",
|
||||
"_release": "3.3.7",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v3.3.7",
|
||||
"commit": "0b9c4a4007c44201dce9a6cc1a38407005c26c86"
|
||||
},
|
||||
"_source": "https://github.com/twbs/bootstrap.git",
|
||||
"_target": "v3.3.7",
|
||||
"_originalSource": "bootstrap",
|
||||
"_direct": true
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2016 Twitter, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -0,0 +1,587 @@
|
|||
/*!
|
||||
* Bootstrap v3.4.1 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
.btn-default,
|
||||
.btn-primary,
|
||||
.btn-success,
|
||||
.btn-info,
|
||||
.btn-warning,
|
||||
.btn-danger {
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.btn-default:active,
|
||||
.btn-primary:active,
|
||||
.btn-success:active,
|
||||
.btn-info:active,
|
||||
.btn-warning:active,
|
||||
.btn-danger:active,
|
||||
.btn-default.active,
|
||||
.btn-primary.active,
|
||||
.btn-success.active,
|
||||
.btn-info.active,
|
||||
.btn-warning.active,
|
||||
.btn-danger.active {
|
||||
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
.btn-default.disabled,
|
||||
.btn-primary.disabled,
|
||||
.btn-success.disabled,
|
||||
.btn-info.disabled,
|
||||
.btn-warning.disabled,
|
||||
.btn-danger.disabled,
|
||||
.btn-default[disabled],
|
||||
.btn-primary[disabled],
|
||||
.btn-success[disabled],
|
||||
.btn-info[disabled],
|
||||
.btn-warning[disabled],
|
||||
.btn-danger[disabled],
|
||||
fieldset[disabled] .btn-default,
|
||||
fieldset[disabled] .btn-primary,
|
||||
fieldset[disabled] .btn-success,
|
||||
fieldset[disabled] .btn-info,
|
||||
fieldset[disabled] .btn-warning,
|
||||
fieldset[disabled] .btn-danger {
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.btn-default .badge,
|
||||
.btn-primary .badge,
|
||||
.btn-success .badge,
|
||||
.btn-info .badge,
|
||||
.btn-warning .badge,
|
||||
.btn-danger .badge {
|
||||
text-shadow: none;
|
||||
}
|
||||
.btn:active,
|
||||
.btn.active {
|
||||
background-image: none;
|
||||
}
|
||||
.btn-default {
|
||||
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
||||
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
|
||||
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dbdbdb;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
border-color: #ccc;
|
||||
}
|
||||
.btn-default:hover,
|
||||
.btn-default:focus {
|
||||
background-color: #e0e0e0;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-default:active,
|
||||
.btn-default.active {
|
||||
background-color: #e0e0e0;
|
||||
border-color: #dbdbdb;
|
||||
}
|
||||
.btn-default.disabled,
|
||||
.btn-default[disabled],
|
||||
fieldset[disabled] .btn-default,
|
||||
.btn-default.disabled:hover,
|
||||
.btn-default[disabled]:hover,
|
||||
fieldset[disabled] .btn-default:hover,
|
||||
.btn-default.disabled:focus,
|
||||
.btn-default[disabled]:focus,
|
||||
fieldset[disabled] .btn-default:focus,
|
||||
.btn-default.disabled.focus,
|
||||
.btn-default[disabled].focus,
|
||||
fieldset[disabled] .btn-default.focus,
|
||||
.btn-default.disabled:active,
|
||||
.btn-default[disabled]:active,
|
||||
fieldset[disabled] .btn-default:active,
|
||||
.btn-default.disabled.active,
|
||||
.btn-default[disabled].active,
|
||||
fieldset[disabled] .btn-default.active {
|
||||
background-color: #e0e0e0;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-primary {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #245580;
|
||||
}
|
||||
.btn-primary:hover,
|
||||
.btn-primary:focus {
|
||||
background-color: #265a88;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-primary:active,
|
||||
.btn-primary.active {
|
||||
background-color: #265a88;
|
||||
border-color: #245580;
|
||||
}
|
||||
.btn-primary.disabled,
|
||||
.btn-primary[disabled],
|
||||
fieldset[disabled] .btn-primary,
|
||||
.btn-primary.disabled:hover,
|
||||
.btn-primary[disabled]:hover,
|
||||
fieldset[disabled] .btn-primary:hover,
|
||||
.btn-primary.disabled:focus,
|
||||
.btn-primary[disabled]:focus,
|
||||
fieldset[disabled] .btn-primary:focus,
|
||||
.btn-primary.disabled.focus,
|
||||
.btn-primary[disabled].focus,
|
||||
fieldset[disabled] .btn-primary.focus,
|
||||
.btn-primary.disabled:active,
|
||||
.btn-primary[disabled]:active,
|
||||
fieldset[disabled] .btn-primary:active,
|
||||
.btn-primary.disabled.active,
|
||||
.btn-primary[disabled].active,
|
||||
fieldset[disabled] .btn-primary.active {
|
||||
background-color: #265a88;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-success {
|
||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
|
||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #3e8f3e;
|
||||
}
|
||||
.btn-success:hover,
|
||||
.btn-success:focus {
|
||||
background-color: #419641;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-success:active,
|
||||
.btn-success.active {
|
||||
background-color: #419641;
|
||||
border-color: #3e8f3e;
|
||||
}
|
||||
.btn-success.disabled,
|
||||
.btn-success[disabled],
|
||||
fieldset[disabled] .btn-success,
|
||||
.btn-success.disabled:hover,
|
||||
.btn-success[disabled]:hover,
|
||||
fieldset[disabled] .btn-success:hover,
|
||||
.btn-success.disabled:focus,
|
||||
.btn-success[disabled]:focus,
|
||||
fieldset[disabled] .btn-success:focus,
|
||||
.btn-success.disabled.focus,
|
||||
.btn-success[disabled].focus,
|
||||
fieldset[disabled] .btn-success.focus,
|
||||
.btn-success.disabled:active,
|
||||
.btn-success[disabled]:active,
|
||||
fieldset[disabled] .btn-success:active,
|
||||
.btn-success.disabled.active,
|
||||
.btn-success[disabled].active,
|
||||
fieldset[disabled] .btn-success.active {
|
||||
background-color: #419641;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-info {
|
||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
|
||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #28a4c9;
|
||||
}
|
||||
.btn-info:hover,
|
||||
.btn-info:focus {
|
||||
background-color: #2aabd2;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-info:active,
|
||||
.btn-info.active {
|
||||
background-color: #2aabd2;
|
||||
border-color: #28a4c9;
|
||||
}
|
||||
.btn-info.disabled,
|
||||
.btn-info[disabled],
|
||||
fieldset[disabled] .btn-info,
|
||||
.btn-info.disabled:hover,
|
||||
.btn-info[disabled]:hover,
|
||||
fieldset[disabled] .btn-info:hover,
|
||||
.btn-info.disabled:focus,
|
||||
.btn-info[disabled]:focus,
|
||||
fieldset[disabled] .btn-info:focus,
|
||||
.btn-info.disabled.focus,
|
||||
.btn-info[disabled].focus,
|
||||
fieldset[disabled] .btn-info.focus,
|
||||
.btn-info.disabled:active,
|
||||
.btn-info[disabled]:active,
|
||||
fieldset[disabled] .btn-info:active,
|
||||
.btn-info.disabled.active,
|
||||
.btn-info[disabled].active,
|
||||
fieldset[disabled] .btn-info.active {
|
||||
background-color: #2aabd2;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-warning {
|
||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
|
||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #e38d13;
|
||||
}
|
||||
.btn-warning:hover,
|
||||
.btn-warning:focus {
|
||||
background-color: #eb9316;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-warning:active,
|
||||
.btn-warning.active {
|
||||
background-color: #eb9316;
|
||||
border-color: #e38d13;
|
||||
}
|
||||
.btn-warning.disabled,
|
||||
.btn-warning[disabled],
|
||||
fieldset[disabled] .btn-warning,
|
||||
.btn-warning.disabled:hover,
|
||||
.btn-warning[disabled]:hover,
|
||||
fieldset[disabled] .btn-warning:hover,
|
||||
.btn-warning.disabled:focus,
|
||||
.btn-warning[disabled]:focus,
|
||||
fieldset[disabled] .btn-warning:focus,
|
||||
.btn-warning.disabled.focus,
|
||||
.btn-warning[disabled].focus,
|
||||
fieldset[disabled] .btn-warning.focus,
|
||||
.btn-warning.disabled:active,
|
||||
.btn-warning[disabled]:active,
|
||||
fieldset[disabled] .btn-warning:active,
|
||||
.btn-warning.disabled.active,
|
||||
.btn-warning[disabled].active,
|
||||
fieldset[disabled] .btn-warning.active {
|
||||
background-color: #eb9316;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-danger {
|
||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
|
||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #b92c28;
|
||||
}
|
||||
.btn-danger:hover,
|
||||
.btn-danger:focus {
|
||||
background-color: #c12e2a;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-danger:active,
|
||||
.btn-danger.active {
|
||||
background-color: #c12e2a;
|
||||
border-color: #b92c28;
|
||||
}
|
||||
.btn-danger.disabled,
|
||||
.btn-danger[disabled],
|
||||
fieldset[disabled] .btn-danger,
|
||||
.btn-danger.disabled:hover,
|
||||
.btn-danger[disabled]:hover,
|
||||
fieldset[disabled] .btn-danger:hover,
|
||||
.btn-danger.disabled:focus,
|
||||
.btn-danger[disabled]:focus,
|
||||
fieldset[disabled] .btn-danger:focus,
|
||||
.btn-danger.disabled.focus,
|
||||
.btn-danger[disabled].focus,
|
||||
fieldset[disabled] .btn-danger.focus,
|
||||
.btn-danger.disabled:active,
|
||||
.btn-danger[disabled]:active,
|
||||
fieldset[disabled] .btn-danger:active,
|
||||
.btn-danger.disabled.active,
|
||||
.btn-danger[disabled].active,
|
||||
fieldset[disabled] .btn-danger.active {
|
||||
background-color: #c12e2a;
|
||||
background-image: none;
|
||||
}
|
||||
.thumbnail,
|
||||
.img-thumbnail {
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus {
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
.dropdown-menu > .active > a,
|
||||
.dropdown-menu > .active > a:hover,
|
||||
.dropdown-menu > .active > a:focus {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
background-color: #2e6da4;
|
||||
}
|
||||
.navbar-default {
|
||||
background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
|
||||
background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));
|
||||
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.navbar-default .navbar-nav > .open > a,
|
||||
.navbar-default .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
||||
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
|
||||
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.navbar-brand,
|
||||
.navbar-nav > li > a {
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
.navbar-inverse {
|
||||
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
||||
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
|
||||
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.navbar-inverse .navbar-nav > .open > a,
|
||||
.navbar-inverse .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
||||
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
|
||||
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.navbar-inverse .navbar-brand,
|
||||
.navbar-inverse .navbar-nav > li > a {
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.navbar-static-top,
|
||||
.navbar-fixed-top,
|
||||
.navbar-fixed-bottom {
|
||||
border-radius: 0;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.navbar .navbar-nav .open .dropdown-menu > .active > a,
|
||||
.navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
|
||||
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
|
||||
color: #fff;
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
}
|
||||
.alert {
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.alert-success {
|
||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
|
||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #b2dba1;
|
||||
}
|
||||
.alert-info {
|
||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
|
||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #9acfea;
|
||||
}
|
||||
.alert-warning {
|
||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
|
||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #f5e79e;
|
||||
}
|
||||
.alert-danger {
|
||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
|
||||
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dca7a7;
|
||||
}
|
||||
.progress {
|
||||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
|
||||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-success {
|
||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
|
||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-info {
|
||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
|
||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-warning {
|
||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
|
||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-danger {
|
||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
|
||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.progress-bar-striped {
|
||||
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||
}
|
||||
.list-group {
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.list-group-item.active,
|
||||
.list-group-item.active:hover,
|
||||
.list-group-item.active:focus {
|
||||
text-shadow: 0 -1px 0 #286090;
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #2b669a;
|
||||
}
|
||||
.list-group-item.active .badge,
|
||||
.list-group-item.active:hover .badge,
|
||||
.list-group-item.active:focus .badge {
|
||||
text-shadow: none;
|
||||
}
|
||||
.panel {
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.panel-default > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-primary > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-success > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
|
||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-info > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
|
||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-warning > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
|
||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.panel-danger > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
|
||||
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.well {
|
||||
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
|
||||
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dcdcdc;
|
||||
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-theme.css.map */
|
After Width: | Height: | Size: 106 KiB |
|
@ -0,0 +1,2580 @@
|
|||
/*!
|
||||
* Bootstrap v3.4.1 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under the MIT license
|
||||
*/
|
||||
|
||||
if (typeof jQuery === 'undefined') {
|
||||
throw new Error('Bootstrap\'s JavaScript requires jQuery')
|
||||
}
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
var version = $.fn.jquery.split(' ')[0].split('.')
|
||||
if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
|
||||
throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
|
||||
}
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: transition.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#transitions
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/)
|
||||
// ============================================================
|
||||
|
||||
function transitionEnd() {
|
||||
var el = document.createElement('bootstrap')
|
||||
|
||||
var transEndEventNames = {
|
||||
WebkitTransition : 'webkitTransitionEnd',
|
||||
MozTransition : 'transitionend',
|
||||
OTransition : 'oTransitionEnd otransitionend',
|
||||
transition : 'transitionend'
|
||||
}
|
||||
|
||||
for (var name in transEndEventNames) {
|
||||
if (el.style[name] !== undefined) {
|
||||
return { end: transEndEventNames[name] }
|
||||
}
|
||||
}
|
||||
|
||||
return false // explicit for ie8 ( ._.)
|
||||
}
|
||||
|
||||
// https://blog.alexmaccaw.com/css-transitions
|
||||
$.fn.emulateTransitionEnd = function (duration) {
|
||||
var called = false
|
||||
var $el = this
|
||||
$(this).one('bsTransitionEnd', function () { called = true })
|
||||
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
|
||||
setTimeout(callback, duration)
|
||||
return this
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$.support.transition = transitionEnd()
|
||||
|
||||
if (!$.support.transition) return
|
||||
|
||||
$.event.special.bsTransitionEnd = {
|
||||
bindType: $.support.transition.end,
|
||||
delegateType: $.support.transition.end,
|
||||
handle: function (e) {
|
||||
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: alert.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#alerts
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// ALERT CLASS DEFINITION
|
||||
// ======================
|
||||
|
||||
var dismiss = '[data-dismiss="alert"]'
|
||||
var Alert = function (el) {
|
||||
$(el).on('click', dismiss, this.close)
|
||||
}
|
||||
|
||||
Alert.VERSION = '3.4.1'
|
||||
|
||||
Alert.TRANSITION_DURATION = 150
|
||||
|
||||
Alert.prototype.close = function (e) {
|
||||
var $this = $(this)
|
||||
var selector = $this.attr('data-target')
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
||||
}
|
||||
|
||||
selector = selector === '#' ? [] : selector
|
||||
var $parent = $(document).find(selector)
|
||||
|
||||
if (e) e.preventDefault()
|
||||
|
||||
if (!$parent.length) {
|
||||
$parent = $this.closest('.alert')
|
||||
}
|
||||
|
||||
$parent.trigger(e = $.Event('close.bs.alert'))
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$parent.removeClass('in')
|
||||
|
||||
function removeElement() {
|
||||
// detach from parent, fire event then clean up data
|
||||
$parent.detach().trigger('closed.bs.alert').remove()
|
||||
}
|
||||
|
||||
$.support.transition && $parent.hasClass('fade') ?
|
||||
$parent
|
||||
.one('bsTransitionEnd', removeElement)
|
||||
.emulateTransitionEnd(Alert.TRANSITION_DURATION) :
|
||||
removeElement()
|
||||
}
|
||||
|
||||
|
||||
// ALERT PLUGIN DEFINITION
|
||||
// =======================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.alert')
|
||||
|
||||
if (!data) $this.data('bs.alert', (data = new Alert(this)))
|
||||
if (typeof option == 'string') data[option].call($this)
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.alert
|
||||
|
||||
$.fn.alert = Plugin
|
||||
$.fn.alert.Constructor = Alert
|
||||
|
||||
|
||||
// ALERT NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.alert.noConflict = function () {
|
||||
$.fn.alert = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// ALERT DATA-API
|
||||
// ==============
|
||||
|
||||
$(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: button.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#buttons
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// BUTTON PUBLIC CLASS DEFINITION
|
||||
// ==============================
|
||||
|
||||
var Button = function (element, options) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, Button.DEFAULTS, options)
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
Button.VERSION = '3.4.1'
|
||||
|
||||
Button.DEFAULTS = {
|
||||
loadingText: 'loading...'
|
||||
}
|
||||
|
||||
Button.prototype.setState = function (state) {
|
||||
var d = 'disabled'
|
||||
var $el = this.$element
|
||||
var val = $el.is('input') ? 'val' : 'html'
|
||||
var data = $el.data()
|
||||
|
||||
state += 'Text'
|
||||
|
||||
if (data.resetText == null) $el.data('resetText', $el[val]())
|
||||
|
||||
// push to event loop to allow forms to submit
|
||||
setTimeout($.proxy(function () {
|
||||
$el[val](data[state] == null ? this.options[state] : data[state])
|
||||
|
||||
if (state == 'loadingText') {
|
||||
this.isLoading = true
|
||||
$el.addClass(d).attr(d, d).prop(d, true)
|
||||
} else if (this.isLoading) {
|
||||
this.isLoading = false
|
||||
$el.removeClass(d).removeAttr(d).prop(d, false)
|
||||
}
|
||||
}, this), 0)
|
||||
}
|
||||
|
||||
Button.prototype.toggle = function () {
|
||||
var changed = true
|
||||
var $parent = this.$element.closest('[data-toggle="buttons"]')
|
||||
|
||||
if ($parent.length) {
|
||||
var $input = this.$element.find('input')
|
||||
if ($input.prop('type') == 'radio') {
|
||||
if ($input.prop('checked')) changed = false
|
||||
$parent.find('.active').removeClass('active')
|
||||
this.$element.addClass('active')
|
||||
} else if ($input.prop('type') == 'checkbox') {
|
||||
if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
|
||||
this.$element.toggleClass('active')
|
||||
}
|
||||
$input.prop('checked', this.$element.hasClass('active'))
|
||||
if (changed) $input.trigger('change')
|
||||
} else {
|
||||
this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
|
||||
this.$element.toggleClass('active')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// BUTTON PLUGIN DEFINITION
|
||||
// ========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.button')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data) $this.data('bs.button', (data = new Button(this, options)))
|
||||
|
||||
if (option == 'toggle') data.toggle()
|
||||
else if (option) data.setState(option)
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.button
|
||||
|
||||
$.fn.button = Plugin
|
||||
$.fn.button.Constructor = Button
|
||||
|
||||
|
||||
// BUTTON NO CONFLICT
|
||||
// ==================
|
||||
|
||||
$.fn.button.noConflict = function () {
|
||||
$.fn.button = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// BUTTON DATA-API
|
||||
// ===============
|
||||
|
||||
$(document)
|
||||
.on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
|
||||
var $btn = $(e.target).closest('.btn')
|
||||
Plugin.call($btn, 'toggle')
|
||||
if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
|
||||
// Prevent double click on radios, and the double selections (so cancellation) on checkboxes
|
||||
e.preventDefault()
|
||||
// The target component still receive the focus
|
||||
if ($btn.is('input,button')) $btn.trigger('focus')
|
||||
else $btn.find('input:visible,button:visible').first().trigger('focus')
|
||||
}
|
||||
})
|
||||
.on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
|
||||
$(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: carousel.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#carousel
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// CAROUSEL CLASS DEFINITION
|
||||
// =========================
|
||||
|
||||
var Carousel = function (element, options) {
|
||||
this.$element = $(element)
|
||||
this.$indicators = this.$element.find('.carousel-indicators')
|
||||
this.options = options
|
||||
this.paused = null
|
||||
this.sliding = null
|
||||
this.interval = null
|
||||
this.$active = null
|
||||
this.$items = null
|
||||
|
||||
this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
|
||||
|
||||
this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
|
||||
.on('mouseenter.bs.carousel', $.proxy(this.pause, this))
|
||||
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
|
||||
}
|
||||
|
||||
Carousel.VERSION = '3.4.1'
|
||||
|
||||
Carousel.TRANSITION_DURATION = 600
|
||||
|
||||
Carousel.DEFAULTS = {
|
||||
interval: 5000,
|
||||
pause: 'hover',
|
||||
wrap: true,
|
||||
keyboard: true
|
||||
}
|
||||
|
||||
Carousel.prototype.keydown = function (e) {
|
||||
if (/input|textarea/i.test(e.target.tagName)) return
|
||||
switch (e.which) {
|
||||
case 37: this.prev(); break
|
||||
case 39: this.next(); break
|
||||
default: return
|
||||
}
|
||||
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
Carousel.prototype.cycle = function (e) {
|
||||
e || (this.paused = false)
|
||||
|
||||
this.interval && clearInterval(this.interval)
|
||||
|
||||
this.options.interval
|
||||
&& !this.paused
|
||||
&& (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
Carousel.prototype.getItemIndex = function (item) {
|
||||
this.$items = item.parent().children('.item')
|
||||
return this.$items.index(item || this.$active)
|
||||
}
|
||||
|
||||
Carousel.prototype.getItemForDirection = function (direction, active) {
|
||||
var activeIndex = this.getItemIndex(active)
|
||||
var willWrap = (direction == 'prev' && activeIndex === 0)
|
||||
|| (direction == 'next' && activeIndex == (this.$items.length - 1))
|
||||
if (willWrap && !this.options.wrap) return active
|
||||
var delta = direction == 'prev' ? -1 : 1
|
||||
var itemIndex = (activeIndex + delta) % this.$items.length
|
||||
return this.$items.eq(itemIndex)
|
||||
}
|
||||
|
||||
Carousel.prototype.to = function (pos) {
|
||||
var that = this
|
||||
var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
|
||||
|
||||
if (pos > (this.$items.length - 1) || pos < 0) return
|
||||
|
||||
if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
|
||||
if (activeIndex == pos) return this.pause().cycle()
|
||||
|
||||
return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
|
||||
}
|
||||
|
||||
Carousel.prototype.pause = function (e) {
|
||||
e || (this.paused = true)
|
||||
|
||||
if (this.$element.find('.next, .prev').length && $.support.transition) {
|
||||
this.$element.trigger($.support.transition.end)
|
||||
this.cycle(true)
|
||||
}
|
||||
|
||||
this.interval = clearInterval(this.interval)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
Carousel.prototype.next = function () {
|
||||
if (this.sliding) return
|
||||
return this.slide('next')
|
||||
}
|
||||
|
||||
Carousel.prototype.prev = function () {
|
||||
if (this.sliding) return
|
||||
return this.slide('prev')
|
||||
}
|
||||
|
||||
Carousel.prototype.slide = function (type, next) {
|
||||
var $active = this.$element.find('.item.active')
|
||||
var $next = next || this.getItemForDirection(type, $active)
|
||||
var isCycling = this.interval
|
||||
var direction = type == 'next' ? 'left' : 'right'
|
||||
var that = this
|
||||
|
||||
if ($next.hasClass('active')) return (this.sliding = false)
|
||||
|
||||
var relatedTarget = $next[0]
|
||||
var slideEvent = $.Event('slide.bs.carousel', {
|
||||
relatedTarget: relatedTarget,
|
||||
direction: direction
|
||||
})
|
||||
this.$element.trigger(slideEvent)
|
||||
if (slideEvent.isDefaultPrevented()) return
|
||||
|
||||
this.sliding = true
|
||||
|
||||
isCycling && this.pause()
|
||||
|
||||
if (this.$indicators.length) {
|
||||
this.$indicators.find('.active').removeClass('active')
|
||||
var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
|
||||
$nextIndicator && $nextIndicator.addClass('active')
|
||||
}
|
||||
|
||||
var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
|
||||
if ($.support.transition && this.$element.hasClass('slide')) {
|
||||
$next.addClass(type)
|
||||
if (typeof $next === 'object' && $next.length) {
|
||||
$next[0].offsetWidth // force reflow
|
||||
}
|
||||
$active.addClass(direction)
|
||||
$next.addClass(direction)
|
||||
$active
|
||||
.one('bsTransitionEnd', function () {
|
||||
$next.removeClass([type, direction].join(' ')).addClass('active')
|
||||
$active.removeClass(['active', direction].join(' '))
|
||||
that.sliding = false
|
||||
setTimeout(function () {
|
||||
that.$element.trigger(slidEvent)
|
||||
}, 0)
|
||||
})
|
||||
.emulateTransitionEnd(Carousel.TRANSITION_DURATION)
|
||||
} else {
|
||||
$active.removeClass('active')
|
||||
$next.addClass('active')
|
||||
this.sliding = false
|
||||
this.$element.trigger(slidEvent)
|
||||
}
|
||||
|
||||
isCycling && this.cycle()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// CAROUSEL PLUGIN DEFINITION
|
||||
// ==========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.carousel')
|
||||
var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
var action = typeof option == 'string' ? option : options.slide
|
||||
|
||||
if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
|
||||
if (typeof option == 'number') data.to(option)
|
||||
else if (action) data[action]()
|
||||
else if (options.interval) data.pause().cycle()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.carousel
|
||||
|
||||
$.fn.carousel = Plugin
|
||||
$.fn.carousel.Constructor = Carousel
|
||||
|
||||
|
||||
// CAROUSEL NO CONFLICT
|
||||
// ====================
|
||||
|
||||
$.fn.carousel.noConflict = function () {
|
||||
$.fn.carousel = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// CAROUSEL DATA-API
|
||||
// =================
|
||||
|
||||
var clickHandler = function (e) {
|
||||
var $this = $(this)
|
||||
var href = $this.attr('href')
|
||||
if (href) {
|
||||
href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
|
||||
}
|
||||
|
||||
var target = $this.attr('data-target') || href
|
||||
var $target = $(document).find(target)
|
||||
|
||||
if (!$target.hasClass('carousel')) return
|
||||
|
||||
var options = $.extend({}, $target.data(), $this.data())
|
||||
var slideIndex = $this.attr('data-slide-to')
|
||||
if (slideIndex) options.interval = false
|
||||
|
||||
Plugin.call($target, options)
|
||||
|
||||
if (slideIndex) {
|
||||
$target.data('bs.carousel').to(slideIndex)
|
||||
}
|
||||
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
$(document)
|
||||
.on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
|
||||
.on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
|
||||
|
||||
$(window).on('load', function () {
|
||||
$('[data-ride="carousel"]').each(function () {
|
||||
var $carousel = $(this)
|
||||
Plugin.call($carousel, $carousel.data())
|
||||
})
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: collapse.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#collapse
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
/* jshint latedef: false */
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// COLLAPSE PUBLIC CLASS DEFINITION
|
||||
// ================================
|
||||
|
||||
var Collapse = function (element, options) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, Collapse.DEFAULTS, options)
|
||||
this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
|
||||
'[data-toggle="collapse"][data-target="#' + element.id + '"]')
|
||||
this.transitioning = null
|
||||
|
||||
if (this.options.parent) {
|
||||
this.$parent = this.getParent()
|
||||
} else {
|
||||
this.addAriaAndCollapsedClass(this.$element, this.$trigger)
|
||||
}
|
||||
|
||||
if (this.options.toggle) this.toggle()
|
||||
}
|
||||
|
||||
Collapse.VERSION = '3.4.1'
|
||||
|
||||
Collapse.TRANSITION_DURATION = 350
|
||||
|
||||
Collapse.DEFAULTS = {
|
||||
toggle: true
|
||||
}
|
||||
|
||||
Collapse.prototype.dimension = function () {
|
||||
var hasWidth = this.$element.hasClass('width')
|
||||
return hasWidth ? 'width' : 'height'
|
||||
}
|
||||
|
||||
Collapse.prototype.show = function () {
|
||||
if (this.transitioning || this.$element.hasClass('in')) return
|
||||
|
||||
var activesData
|
||||
var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
|
||||
|
||||
if (actives && actives.length) {
|
||||
activesData = actives.data('bs.collapse')
|
||||
if (activesData && activesData.transitioning) return
|
||||
}
|
||||
|
||||
var startEvent = $.Event('show.bs.collapse')
|
||||
this.$element.trigger(startEvent)
|
||||
if (startEvent.isDefaultPrevented()) return
|
||||
|
||||
if (actives && actives.length) {
|
||||
Plugin.call(actives, 'hide')
|
||||
activesData || actives.data('bs.collapse', null)
|
||||
}
|
||||
|
||||
var dimension = this.dimension()
|
||||
|
||||
this.$element
|
||||
.removeClass('collapse')
|
||||
.addClass('collapsing')[dimension](0)
|
||||
.attr('aria-expanded', true)
|
||||
|
||||
this.$trigger
|
||||
.removeClass('collapsed')
|
||||
.attr('aria-expanded', true)
|
||||
|
||||
this.transitioning = 1
|
||||
|
||||
var complete = function () {
|
||||
this.$element
|
||||
.removeClass('collapsing')
|
||||
.addClass('collapse in')[dimension]('')
|
||||
this.transitioning = 0
|
||||
this.$element
|
||||
.trigger('shown.bs.collapse')
|
||||
}
|
||||
|
||||
if (!$.support.transition) return complete.call(this)
|
||||
|
||||
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
|
||||
|
||||
this.$element
|
||||
.one('bsTransitionEnd', $.proxy(complete, this))
|
||||
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
|
||||
}
|
||||
|
||||
Collapse.prototype.hide = function () {
|
||||
if (this.transitioning || !this.$element.hasClass('in')) return
|
||||
|
||||
var startEvent = $.Event('hide.bs.collapse')
|
||||
this.$element.trigger(startEvent)
|
||||
if (startEvent.isDefaultPrevented()) return
|
||||
|
||||
var dimension = this.dimension()
|
||||
|
||||
this.$element[dimension](this.$element[dimension]())[0].offsetHeight
|
||||
|
||||
this.$element
|
||||
.addClass('collapsing')
|
||||
.removeClass('collapse in')
|
||||
.attr('aria-expanded', false)
|
||||
|
||||
this.$trigger
|
||||
.addClass('collapsed')
|
||||
.attr('aria-expanded', false)
|
||||
|
||||
this.transitioning = 1
|
||||
|
||||
var complete = function () {
|
||||
this.transitioning = 0
|
||||
this.$element
|
||||
.removeClass('collapsing')
|
||||
.addClass('collapse')
|
||||
.trigger('hidden.bs.collapse')
|
||||
}
|
||||
|
||||
if (!$.support.transition) return complete.call(this)
|
||||
|
||||
this.$element
|
||||
[dimension](0)
|
||||
.one('bsTransitionEnd', $.proxy(complete, this))
|
||||
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)
|
||||
}
|
||||
|
||||
Collapse.prototype.toggle = function () {
|
||||
this[this.$element.hasClass('in') ? 'hide' : 'show']()
|
||||
}
|
||||
|
||||
Collapse.prototype.getParent = function () {
|
||||
return $(document).find(this.options.parent)
|
||||
.find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
|
||||
.each($.proxy(function (i, element) {
|
||||
var $element = $(element)
|
||||
this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
|
||||
}, this))
|
||||
.end()
|
||||
}
|
||||
|
||||
Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
|
||||
var isOpen = $element.hasClass('in')
|
||||
|
||||
$element.attr('aria-expanded', isOpen)
|
||||
$trigger
|
||||
.toggleClass('collapsed', !isOpen)
|
||||
.attr('aria-expanded', isOpen)
|
||||
}
|
||||
|
||||
function getTargetFromTrigger($trigger) {
|
||||
var href
|
||||
var target = $trigger.attr('data-target')
|
||||
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
|
||||
|
||||
return $(document).find(target)
|
||||
}
|
||||
|
||||
|
||||
// COLLAPSE PLUGIN DEFINITION
|
||||
// ==========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.collapse')
|
||||
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
|
||||
if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
|
||||
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.collapse
|
||||
|
||||
$.fn.collapse = Plugin
|
||||
$.fn.collapse.Constructor = Collapse
|
||||
|
||||
|
||||
// COLLAPSE NO CONFLICT
|
||||
// ====================
|
||||
|
||||
$.fn.collapse.noConflict = function () {
|
||||
$.fn.collapse = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// COLLAPSE DATA-API
|
||||
// =================
|
||||
|
||||
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
|
||||
var $this = $(this)
|
||||
|
||||
if (!$this.attr('data-target')) e.preventDefault()
|
||||
|
||||
var $target = getTargetFromTrigger($this)
|
||||
var data = $target.data('bs.collapse')
|
||||
var option = data ? 'toggle' : $this.data()
|
||||
|
||||
Plugin.call($target, option)
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: dropdown.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#dropdowns
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// DROPDOWN CLASS DEFINITION
|
||||
// =========================
|
||||
|
||||
var backdrop = '.dropdown-backdrop'
|
||||
var toggle = '[data-toggle="dropdown"]'
|
||||
var Dropdown = function (element) {
|
||||
$(element).on('click.bs.dropdown', this.toggle)
|
||||
}
|
||||
|
||||
Dropdown.VERSION = '3.4.1'
|
||||
|
||||
function getParent($this) {
|
||||
var selector = $this.attr('data-target')
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
||||
}
|
||||
|
||||
var $parent = selector !== '#' ? $(document).find(selector) : null
|
||||
|
||||
return $parent && $parent.length ? $parent : $this.parent()
|
||||
}
|
||||
|
||||
function clearMenus(e) {
|
||||
if (e && e.which === 3) return
|
||||
$(backdrop).remove()
|
||||
$(toggle).each(function () {
|
||||
var $this = $(this)
|
||||
var $parent = getParent($this)
|
||||
var relatedTarget = { relatedTarget: this }
|
||||
|
||||
if (!$parent.hasClass('open')) return
|
||||
|
||||
if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
|
||||
|
||||
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$this.attr('aria-expanded', 'false')
|
||||
$parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
|
||||
})
|
||||
}
|
||||
|
||||
Dropdown.prototype.toggle = function (e) {
|
||||
var $this = $(this)
|
||||
|
||||
if ($this.is('.disabled, :disabled')) return
|
||||
|
||||
var $parent = getParent($this)
|
||||
var isActive = $parent.hasClass('open')
|
||||
|
||||
clearMenus()
|
||||
|
||||
if (!isActive) {
|
||||
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
|
||||
// if mobile we use a backdrop because click events don't delegate
|
||||
$(document.createElement('div'))
|
||||
.addClass('dropdown-backdrop')
|
||||
.insertAfter($(this))
|
||||
.on('click', clearMenus)
|
||||
}
|
||||
|
||||
var relatedTarget = { relatedTarget: this }
|
||||
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$this
|
||||
.trigger('focus')
|
||||
.attr('aria-expanded', 'true')
|
||||
|
||||
$parent
|
||||
.toggleClass('open')
|
||||
.trigger($.Event('shown.bs.dropdown', relatedTarget))
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Dropdown.prototype.keydown = function (e) {
|
||||
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
|
||||
|
||||
var $this = $(this)
|
||||
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
if ($this.is('.disabled, :disabled')) return
|
||||
|
||||
var $parent = getParent($this)
|
||||
var isActive = $parent.hasClass('open')
|
||||
|
||||
if (!isActive && e.which != 27 || isActive && e.which == 27) {
|
||||
if (e.which == 27) $parent.find(toggle).trigger('focus')
|
||||
return $this.trigger('click')
|
||||
}
|
||||
|
||||
var desc = ' li:not(.disabled):visible a'
|
||||
var $items = $parent.find('.dropdown-menu' + desc)
|
||||
|
||||
if (!$items.length) return
|
||||
|
||||
var index = $items.index(e.target)
|
||||
|
||||
if (e.which == 38 && index > 0) index-- // up
|
||||
if (e.which == 40 && index < $items.length - 1) index++ // down
|
||||
if (!~index) index = 0
|
||||
|
||||
$items.eq(index).trigger('focus')
|
||||
}
|
||||
|
||||
|
||||
// DROPDOWN PLUGIN DEFINITION
|
||||
// ==========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.dropdown')
|
||||
|
||||
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
|
||||
if (typeof option == 'string') data[option].call($this)
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.dropdown
|
||||
|
||||
$.fn.dropdown = Plugin
|
||||
$.fn.dropdown.Constructor = Dropdown
|
||||
|
||||
|
||||
// DROPDOWN NO CONFLICT
|
||||
// ====================
|
||||
|
||||
$.fn.dropdown.noConflict = function () {
|
||||
$.fn.dropdown = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// APPLY TO STANDARD DROPDOWN ELEMENTS
|
||||
// ===================================
|
||||
|
||||
$(document)
|
||||
.on('click.bs.dropdown.data-api', clearMenus)
|
||||
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
|
||||
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
|
||||
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
|
||||
.on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: modal.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#modals
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// MODAL CLASS DEFINITION
|
||||
// ======================
|
||||
|
||||
var Modal = function (element, options) {
|
||||
this.options = options
|
||||
this.$body = $(document.body)
|
||||
this.$element = $(element)
|
||||
this.$dialog = this.$element.find('.modal-dialog')
|
||||
this.$backdrop = null
|
||||
this.isShown = null
|
||||
this.originalBodyPad = null
|
||||
this.scrollbarWidth = 0
|
||||
this.ignoreBackdropClick = false
|
||||
this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom'
|
||||
|
||||
if (this.options.remote) {
|
||||
this.$element
|
||||
.find('.modal-content')
|
||||
.load(this.options.remote, $.proxy(function () {
|
||||
this.$element.trigger('loaded.bs.modal')
|
||||
}, this))
|
||||
}
|
||||
}
|
||||
|
||||
Modal.VERSION = '3.4.1'
|
||||
|
||||
Modal.TRANSITION_DURATION = 300
|
||||
Modal.BACKDROP_TRANSITION_DURATION = 150
|
||||
|
||||
Modal.DEFAULTS = {
|
||||
backdrop: true,
|
||||
keyboard: true,
|
||||
show: true
|
||||
}
|
||||
|
||||
Modal.prototype.toggle = function (_relatedTarget) {
|
||||
return this.isShown ? this.hide() : this.show(_relatedTarget)
|
||||
}
|
||||
|
||||
Modal.prototype.show = function (_relatedTarget) {
|
||||
var that = this
|
||||
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (this.isShown || e.isDefaultPrevented()) return
|
||||
|
||||
this.isShown = true
|
||||
|
||||
this.checkScrollbar()
|
||||
this.setScrollbar()
|
||||
this.$body.addClass('modal-open')
|
||||
|
||||
this.escape()
|
||||
this.resize()
|
||||
|
||||
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
|
||||
|
||||
this.$dialog.on('mousedown.dismiss.bs.modal', function () {
|
||||
that.$element.one('mouseup.dismiss.bs.modal', function (e) {
|
||||
if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
|
||||
})
|
||||
})
|
||||
|
||||
this.backdrop(function () {
|
||||
var transition = $.support.transition && that.$element.hasClass('fade')
|
||||
|
||||
if (!that.$element.parent().length) {
|
||||
that.$element.appendTo(that.$body) // don't move modals dom position
|
||||
}
|
||||
|
||||
that.$element
|
||||
.show()
|
||||
.scrollTop(0)
|
||||
|
||||
that.adjustDialog()
|
||||
|
||||
if (transition) {
|
||||
that.$element[0].offsetWidth // force reflow
|
||||
}
|
||||
|
||||
that.$element.addClass('in')
|
||||
|
||||
that.enforceFocus()
|
||||
|
||||
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
|
||||
|
||||
transition ?
|
||||
that.$dialog // wait for modal to slide in
|
||||
.one('bsTransitionEnd', function () {
|
||||
that.$element.trigger('focus').trigger(e)
|
||||
})
|
||||
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
|
||||
that.$element.trigger('focus').trigger(e)
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.hide = function (e) {
|
||||
if (e) e.preventDefault()
|
||||
|
||||
e = $.Event('hide.bs.modal')
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (!this.isShown || e.isDefaultPrevented()) return
|
||||
|
||||
this.isShown = false
|
||||
|
||||
this.escape()
|
||||
this.resize()
|
||||
|
||||
$(document).off('focusin.bs.modal')
|
||||
|
||||
this.$element
|
||||
.removeClass('in')
|
||||
.off('click.dismiss.bs.modal')
|
||||
.off('mouseup.dismiss.bs.modal')
|
||||
|
||||
this.$dialog.off('mousedown.dismiss.bs.modal')
|
||||
|
||||
$.support.transition && this.$element.hasClass('fade') ?
|
||||
this.$element
|
||||
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
|
||||
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
|
||||
this.hideModal()
|
||||
}
|
||||
|
||||
Modal.prototype.enforceFocus = function () {
|
||||
$(document)
|
||||
.off('focusin.bs.modal') // guard against infinite focus loop
|
||||
.on('focusin.bs.modal', $.proxy(function (e) {
|
||||
if (document !== e.target &&
|
||||
this.$element[0] !== e.target &&
|
||||
!this.$element.has(e.target).length) {
|
||||
this.$element.trigger('focus')
|
||||
}
|
||||
}, this))
|
||||
}
|
||||
|
||||
Modal.prototype.escape = function () {
|
||||
if (this.isShown && this.options.keyboard) {
|
||||
this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
|
||||
e.which == 27 && this.hide()
|
||||
}, this))
|
||||
} else if (!this.isShown) {
|
||||
this.$element.off('keydown.dismiss.bs.modal')
|
||||
}
|
||||
}
|
||||
|
||||
Modal.prototype.resize = function () {
|
||||
if (this.isShown) {
|
||||
$(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
|
||||
} else {
|
||||
$(window).off('resize.bs.modal')
|
||||
}
|
||||
}
|
||||
|
||||
Modal.prototype.hideModal = function () {
|
||||
var that = this
|
||||
this.$element.hide()
|
||||
this.backdrop(function () {
|
||||
that.$body.removeClass('modal-open')
|
||||
that.resetAdjustments()
|
||||
that.resetScrollbar()
|
||||
that.$element.trigger('hidden.bs.modal')
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.removeBackdrop = function () {
|
||||
this.$backdrop && this.$backdrop.remove()
|
||||
this.$backdrop = null
|
||||
}
|
||||
|
||||
Modal.prototype.backdrop = function (callback) {
|
||||
var that = this
|
||||
var animate = this.$element.hasClass('fade') ? 'fade' : ''
|
||||
|
||||
if (this.isShown && this.options.backdrop) {
|
||||
var doAnimate = $.support.transition && animate
|
||||
|
||||
this.$backdrop = $(document.createElement('div'))
|
||||
.addClass('modal-backdrop ' + animate)
|
||||
.appendTo(this.$body)
|
||||
|
||||
this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
|
||||
if (this.ignoreBackdropClick) {
|
||||
this.ignoreBackdropClick = false
|
||||
return
|
||||
}
|
||||
if (e.target !== e.currentTarget) return
|
||||
this.options.backdrop == 'static'
|
||||
? this.$element[0].focus()
|
||||
: this.hide()
|
||||
}, this))
|
||||
|
||||
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
|
||||
|
||||
this.$backdrop.addClass('in')
|
||||
|
||||
if (!callback) return
|
||||
|
||||
doAnimate ?
|
||||
this.$backdrop
|
||||
.one('bsTransitionEnd', callback)
|
||||
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
|
||||
callback()
|
||||
|
||||
} else if (!this.isShown && this.$backdrop) {
|
||||
this.$backdrop.removeClass('in')
|
||||
|
||||
var callbackRemove = function () {
|
||||
that.removeBackdrop()
|
||||
callback && callback()
|
||||
}
|
||||
$.support.transition && this.$element.hasClass('fade') ?
|
||||
this.$backdrop
|
||||
.one('bsTransitionEnd', callbackRemove)
|
||||
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
|
||||
callbackRemove()
|
||||
|
||||
} else if (callback) {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
// these following methods are used to handle overflowing modals
|
||||
|
||||
Modal.prototype.handleUpdate = function () {
|
||||
this.adjustDialog()
|
||||
}
|
||||
|
||||
Modal.prototype.adjustDialog = function () {
|
||||
var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
|
||||
|
||||
this.$element.css({
|
||||
paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
|
||||
paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.resetAdjustments = function () {
|
||||
this.$element.css({
|
||||
paddingLeft: '',
|
||||
paddingRight: ''
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.checkScrollbar = function () {
|
||||
var fullWindowWidth = window.innerWidth
|
||||
if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
|
||||
var documentElementRect = document.documentElement.getBoundingClientRect()
|
||||
fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
|
||||
}
|
||||
this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
|
||||
this.scrollbarWidth = this.measureScrollbar()
|
||||
}
|
||||
|
||||
Modal.prototype.setScrollbar = function () {
|
||||
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
|
||||
this.originalBodyPad = document.body.style.paddingRight || ''
|
||||
var scrollbarWidth = this.scrollbarWidth
|
||||
if (this.bodyIsOverflowing) {
|
||||
this.$body.css('padding-right', bodyPad + scrollbarWidth)
|
||||
$(this.fixedContent).each(function (index, element) {
|
||||
var actualPadding = element.style.paddingRight
|
||||
var calculatedPadding = $(element).css('padding-right')
|
||||
$(element)
|
||||
.data('padding-right', actualPadding)
|
||||
.css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Modal.prototype.resetScrollbar = function () {
|
||||
this.$body.css('padding-right', this.originalBodyPad)
|
||||
$(this.fixedContent).each(function (index, element) {
|
||||
var padding = $(element).data('padding-right')
|
||||
$(element).removeData('padding-right')
|
||||
element.style.paddingRight = padding ? padding : ''
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.measureScrollbar = function () { // thx walsh
|
||||
var scrollDiv = document.createElement('div')
|
||||
scrollDiv.className = 'modal-scrollbar-measure'
|
||||
this.$body.append(scrollDiv)
|
||||
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
|
||||
this.$body[0].removeChild(scrollDiv)
|
||||
return scrollbarWidth
|
||||
}
|
||||
|
||||
|
||||
// MODAL PLUGIN DEFINITION
|
||||
// =======================
|
||||
|
||||
function Plugin(option, _relatedTarget) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.modal')
|
||||
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
|
||||
if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
|
||||
if (typeof option == 'string') data[option](_relatedTarget)
|
||||
else if (options.show) data.show(_relatedTarget)
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.modal
|
||||
|
||||
$.fn.modal = Plugin
|
||||
$.fn.modal.Constructor = Modal
|
||||
|
||||
|
||||
// MODAL NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.modal.noConflict = function () {
|
||||
$.fn.modal = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// MODAL DATA-API
|
||||
// ==============
|
||||
|
||||
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
|
||||
var $this = $(this)
|
||||
var href = $this.attr('href')
|
||||
var target = $this.attr('data-target') ||
|
||||
(href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
|
||||
|
||||
var $target = $(document).find(target)
|
||||
var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
|
||||
|
||||
if ($this.is('a')) e.preventDefault()
|
||||
|
||||
$target.one('show.bs.modal', function (showEvent) {
|
||||
if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
|
||||
$target.one('hidden.bs.modal', function () {
|
||||
$this.is(':visible') && $this.trigger('focus')
|
||||
})
|
||||
})
|
||||
Plugin.call($target, option, this)
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: tooltip.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#tooltip
|
||||
* Inspired by the original jQuery.tipsy by Jason Frame
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']
|
||||
|
||||
var uriAttrs = [
|
||||
'background',
|
||||
'cite',
|
||||
'href',
|
||||
'itemtype',
|
||||
'longdesc',
|
||||
'poster',
|
||||
'src',
|
||||
'xlink:href'
|
||||
]
|
||||
|
||||
var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
|
||||
|
||||
var DefaultWhitelist = {
|
||||
// Global attributes allowed on any supplied element below.
|
||||
'*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
|
||||
a: ['target', 'href', 'title', 'rel'],
|
||||
area: [],
|
||||
b: [],
|
||||
br: [],
|
||||
col: [],
|
||||
code: [],
|
||||
div: [],
|
||||
em: [],
|
||||
hr: [],
|
||||
h1: [],
|
||||
h2: [],
|
||||
h3: [],
|
||||
h4: [],
|
||||
h5: [],
|
||||
h6: [],
|
||||
i: [],
|
||||
img: ['src', 'alt', 'title', 'width', 'height'],
|
||||
li: [],
|
||||
ol: [],
|
||||
p: [],
|
||||
pre: [],
|
||||
s: [],
|
||||
small: [],
|
||||
span: [],
|
||||
sub: [],
|
||||
sup: [],
|
||||
strong: [],
|
||||
u: [],
|
||||
ul: []
|
||||
}
|
||||
|
||||
/**
|
||||
* A pattern that recognizes a commonly useful subset of URLs that are safe.
|
||||
*
|
||||
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
|
||||
*/
|
||||
var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi
|
||||
|
||||
/**
|
||||
* A pattern that matches safe data URLs. Only matches image, video and audio types.
|
||||
*
|
||||
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
|
||||
*/
|
||||
var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i
|
||||
|
||||
function allowedAttribute(attr, allowedAttributeList) {
|
||||
var attrName = attr.nodeName.toLowerCase()
|
||||
|
||||
if ($.inArray(attrName, allowedAttributeList) !== -1) {
|
||||
if ($.inArray(attrName, uriAttrs) !== -1) {
|
||||
return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
var regExp = $(allowedAttributeList).filter(function (index, value) {
|
||||
return value instanceof RegExp
|
||||
})
|
||||
|
||||
// Check if a regular expression validates the attribute.
|
||||
for (var i = 0, l = regExp.length; i < l; i++) {
|
||||
if (attrName.match(regExp[i])) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
|
||||
if (unsafeHtml.length === 0) {
|
||||
return unsafeHtml
|
||||
}
|
||||
|
||||
if (sanitizeFn && typeof sanitizeFn === 'function') {
|
||||
return sanitizeFn(unsafeHtml)
|
||||
}
|
||||
|
||||
// IE 8 and below don't support createHTMLDocument
|
||||
if (!document.implementation || !document.implementation.createHTMLDocument) {
|
||||
return unsafeHtml
|
||||
}
|
||||
|
||||
var createdDocument = document.implementation.createHTMLDocument('sanitization')
|
||||
createdDocument.body.innerHTML = unsafeHtml
|
||||
|
||||
var whitelistKeys = $.map(whiteList, function (el, i) { return i })
|
||||
var elements = $(createdDocument.body).find('*')
|
||||
|
||||
for (var i = 0, len = elements.length; i < len; i++) {
|
||||
var el = elements[i]
|
||||
var elName = el.nodeName.toLowerCase()
|
||||
|
||||
if ($.inArray(elName, whitelistKeys) === -1) {
|
||||
el.parentNode.removeChild(el)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
var attributeList = $.map(el.attributes, function (el) { return el })
|
||||
var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])
|
||||
|
||||
for (var j = 0, len2 = attributeList.length; j < len2; j++) {
|
||||
if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {
|
||||
el.removeAttribute(attributeList[j].nodeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return createdDocument.body.innerHTML
|
||||
}
|
||||
|
||||
// TOOLTIP PUBLIC CLASS DEFINITION
|
||||
// ===============================
|
||||
|
||||
var Tooltip = function (element, options) {
|
||||
this.type = null
|
||||
this.options = null
|
||||
this.enabled = null
|
||||
this.timeout = null
|
||||
this.hoverState = null
|
||||
this.$element = null
|
||||
this.inState = null
|
||||
|
||||
this.init('tooltip', element, options)
|
||||
}
|
||||
|
||||
Tooltip.VERSION = '3.4.1'
|
||||
|
||||
Tooltip.TRANSITION_DURATION = 150
|
||||
|
||||
Tooltip.DEFAULTS = {
|
||||
animation: true,
|
||||
placement: 'top',
|
||||
selector: false,
|
||||
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
|
||||
trigger: 'hover focus',
|
||||
title: '',
|
||||
delay: 0,
|
||||
html: false,
|
||||
container: false,
|
||||
viewport: {
|
||||
selector: 'body',
|
||||
padding: 0
|
||||
},
|
||||
sanitize : true,
|
||||
sanitizeFn : null,
|
||||
whiteList : DefaultWhitelist
|
||||
}
|
||||
|
||||
Tooltip.prototype.init = function (type, element, options) {
|
||||
this.enabled = true
|
||||
this.type = type
|
||||
this.$element = $(element)
|
||||
this.options = this.getOptions(options)
|
||||
this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
|
||||
this.inState = { click: false, hover: false, focus: false }
|
||||
|
||||
if (this.$element[0] instanceof document.constructor && !this.options.selector) {
|
||||
throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
|
||||
}
|
||||
|
||||
var triggers = this.options.trigger.split(' ')
|
||||
|
||||
for (var i = triggers.length; i--;) {
|
||||
var trigger = triggers[i]
|
||||
|
||||
if (trigger == 'click') {
|
||||
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
|
||||
} else if (trigger != 'manual') {
|
||||
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
|
||||
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
|
||||
|
||||
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
|
||||
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
|
||||
}
|
||||
}
|
||||
|
||||
this.options.selector ?
|
||||
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
|
||||
this.fixTitle()
|
||||
}
|
||||
|
||||
Tooltip.prototype.getDefaults = function () {
|
||||
return Tooltip.DEFAULTS
|
||||
}
|
||||
|
||||
Tooltip.prototype.getOptions = function (options) {
|
||||
var dataAttributes = this.$element.data()
|
||||
|
||||
for (var dataAttr in dataAttributes) {
|
||||
if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
|
||||
delete dataAttributes[dataAttr]
|
||||
}
|
||||
}
|
||||
|
||||
options = $.extend({}, this.getDefaults(), dataAttributes, options)
|
||||
|
||||
if (options.delay && typeof options.delay == 'number') {
|
||||
options.delay = {
|
||||
show: options.delay,
|
||||
hide: options.delay
|
||||
}
|
||||
}
|
||||
|
||||
if (options.sanitize) {
|
||||
options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn)
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
Tooltip.prototype.getDelegateOptions = function () {
|
||||
var options = {}
|
||||
var defaults = this.getDefaults()
|
||||
|
||||
this._options && $.each(this._options, function (key, value) {
|
||||
if (defaults[key] != value) options[key] = value
|
||||
})
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
Tooltip.prototype.enter = function (obj) {
|
||||
var self = obj instanceof this.constructor ?
|
||||
obj : $(obj.currentTarget).data('bs.' + this.type)
|
||||
|
||||
if (!self) {
|
||||
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
|
||||
$(obj.currentTarget).data('bs.' + this.type, self)
|
||||
}
|
||||
|
||||
if (obj instanceof $.Event) {
|
||||
self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
|
||||
}
|
||||
|
||||
if (self.tip().hasClass('in') || self.hoverState == 'in') {
|
||||
self.hoverState = 'in'
|
||||
return
|
||||
}
|
||||
|
||||
clearTimeout(self.timeout)
|
||||
|
||||
self.hoverState = 'in'
|
||||
|
||||
if (!self.options.delay || !self.options.delay.show) return self.show()
|
||||
|
||||
self.timeout = setTimeout(function () {
|
||||
if (self.hoverState == 'in') self.show()
|
||||
}, self.options.delay.show)
|
||||
}
|
||||
|
||||
Tooltip.prototype.isInStateTrue = function () {
|
||||
for (var key in this.inState) {
|
||||
if (this.inState[key]) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Tooltip.prototype.leave = function (obj) {
|
||||
var self = obj instanceof this.constructor ?
|
||||
obj : $(obj.currentTarget).data('bs.' + this.type)
|
||||
|
||||
if (!self) {
|
||||
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
|
||||
$(obj.currentTarget).data('bs.' + this.type, self)
|
||||
}
|
||||
|
||||
if (obj instanceof $.Event) {
|
||||
self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
|
||||
}
|
||||
|
||||
if (self.isInStateTrue()) return
|
||||
|
||||
clearTimeout(self.timeout)
|
||||
|
||||
self.hoverState = 'out'
|
||||
|
||||
if (!self.options.delay || !self.options.delay.hide) return self.hide()
|
||||
|
||||
self.timeout = setTimeout(function () {
|
||||
if (self.hoverState == 'out') self.hide()
|
||||
}, self.options.delay.hide)
|
||||
}
|
||||
|
||||
Tooltip.prototype.show = function () {
|
||||
var e = $.Event('show.bs.' + this.type)
|
||||
|
||||
if (this.hasContent() && this.enabled) {
|
||||
this.$element.trigger(e)
|
||||
|
||||
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
|
||||
if (e.isDefaultPrevented() || !inDom) return
|
||||
var that = this
|
||||
|
||||
var $tip = this.tip()
|
||||
|
||||
var tipId = this.getUID(this.type)
|
||||
|
||||
this.setContent()
|
||||
$tip.attr('id', tipId)
|
||||
this.$element.attr('aria-describedby', tipId)
|
||||
|
||||
if (this.options.animation) $tip.addClass('fade')
|
||||
|
||||
var placement = typeof this.options.placement == 'function' ?
|
||||
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
||||
this.options.placement
|
||||
|
||||
var autoToken = /\s?auto?\s?/i
|
||||
var autoPlace = autoToken.test(placement)
|
||||
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
|
||||
|
||||
$tip
|
||||
.detach()
|
||||
.css({ top: 0, left: 0, display: 'block' })
|
||||
.addClass(placement)
|
||||
.data('bs.' + this.type, this)
|
||||
|
||||
this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
|
||||
this.$element.trigger('inserted.bs.' + this.type)
|
||||
|
||||
var pos = this.getPosition()
|
||||
var actualWidth = $tip[0].offsetWidth
|
||||
var actualHeight = $tip[0].offsetHeight
|
||||
|
||||
if (autoPlace) {
|
||||
var orgPlacement = placement
|
||||
var viewportDim = this.getPosition(this.$viewport)
|
||||
|
||||
placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
|
||||
placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
|
||||
placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
|
||||
placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
|
||||
placement
|
||||
|
||||
$tip
|
||||
.removeClass(orgPlacement)
|
||||
.addClass(placement)
|
||||
}
|
||||
|
||||
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
|
||||
|
||||
this.applyPlacement(calculatedOffset, placement)
|
||||
|
||||
var complete = function () {
|
||||
var prevHoverState = that.hoverState
|
||||
that.$element.trigger('shown.bs.' + that.type)
|
||||
that.hoverState = null
|
||||
|
||||
if (prevHoverState == 'out') that.leave(that)
|
||||
}
|
||||
|
||||
$.support.transition && this.$tip.hasClass('fade') ?
|
||||
$tip
|
||||
.one('bsTransitionEnd', complete)
|
||||
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
|
||||
complete()
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.prototype.applyPlacement = function (offset, placement) {
|
||||
var $tip = this.tip()
|
||||
var width = $tip[0].offsetWidth
|
||||
var height = $tip[0].offsetHeight
|
||||
|
||||
// manually read margins because getBoundingClientRect includes difference
|
||||
var marginTop = parseInt($tip.css('margin-top'), 10)
|
||||
var marginLeft = parseInt($tip.css('margin-left'), 10)
|
||||
|
||||
// we must check for NaN for ie 8/9
|
||||
if (isNaN(marginTop)) marginTop = 0
|
||||
if (isNaN(marginLeft)) marginLeft = 0
|
||||
|
||||
offset.top += marginTop
|
||||
offset.left += marginLeft
|
||||
|
||||
// $.fn.offset doesn't round pixel values
|
||||
// so we use setOffset directly with our own function B-0
|
||||
$.offset.setOffset($tip[0], $.extend({
|
||||
using: function (props) {
|
||||
$tip.css({
|
||||
top: Math.round(props.top),
|
||||
left: Math.round(props.left)
|
||||
})
|
||||
}
|
||||
}, offset), 0)
|
||||
|
||||
$tip.addClass('in')
|
||||
|
||||
// check to see if placing tip in new offset caused the tip to resize itself
|
||||
var actualWidth = $tip[0].offsetWidth
|
||||
var actualHeight = $tip[0].offsetHeight
|
||||
|
||||
if (placement == 'top' && actualHeight != height) {
|
||||
offset.top = offset.top + height - actualHeight
|
||||
}
|
||||
|
||||
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
|
||||
|
||||
if (delta.left) offset.left += delta.left
|
||||
else offset.top += delta.top
|
||||
|
||||
var isVertical = /top|bottom/.test(placement)
|
||||
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
|
||||
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
|
||||
|
||||
$tip.offset(offset)
|
||||
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
|
||||
}
|
||||
|
||||
Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
|
||||
this.arrow()
|
||||
.css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
|
||||
.css(isVertical ? 'top' : 'left', '')
|
||||
}
|
||||
|
||||
Tooltip.prototype.setContent = function () {
|
||||
var $tip = this.tip()
|
||||
var title = this.getTitle()
|
||||
|
||||
if (this.options.html) {
|
||||
if (this.options.sanitize) {
|
||||
title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn)
|
||||
}
|
||||
|
||||
$tip.find('.tooltip-inner').html(title)
|
||||
} else {
|
||||
$tip.find('.tooltip-inner').text(title)
|
||||
}
|
||||
|
||||
$tip.removeClass('fade in top bottom left right')
|
||||
}
|
||||
|
||||
Tooltip.prototype.hide = function (callback) {
|
||||
var that = this
|
||||
var $tip = $(this.$tip)
|
||||
var e = $.Event('hide.bs.' + this.type)
|
||||
|
||||
function complete() {
|
||||
if (that.hoverState != 'in') $tip.detach()
|
||||
if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
|
||||
that.$element
|
||||
.removeAttr('aria-describedby')
|
||||
.trigger('hidden.bs.' + that.type)
|
||||
}
|
||||
callback && callback()
|
||||
}
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$tip.removeClass('in')
|
||||
|
||||
$.support.transition && $tip.hasClass('fade') ?
|
||||
$tip
|
||||
.one('bsTransitionEnd', complete)
|
||||
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
|
||||
complete()
|
||||
|
||||
this.hoverState = null
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
Tooltip.prototype.fixTitle = function () {
|
||||
var $e = this.$element
|
||||
if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
|
||||
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.prototype.hasContent = function () {
|
||||
return this.getTitle()
|
||||
}
|
||||
|
||||
Tooltip.prototype.getPosition = function ($element) {
|
||||
$element = $element || this.$element
|
||||
|
||||
var el = $element[0]
|
||||
var isBody = el.tagName == 'BODY'
|
||||
|
||||
var elRect = el.getBoundingClientRect()
|
||||
if (elRect.width == null) {
|
||||
// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
|
||||
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
|
||||
}
|
||||
var isSvg = window.SVGElement && el instanceof window.SVGElement
|
||||
// Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
|
||||
// See https://github.com/twbs/bootstrap/issues/20280
|
||||
var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
|
||||
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
|
||||
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
|
||||
|
||||
return $.extend({}, elRect, scroll, outerDims, elOffset)
|
||||
}
|
||||
|
||||
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
|
||||
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
||||
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
||||
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
|
||||
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
|
||||
|
||||
}
|
||||
|
||||
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
|
||||
var delta = { top: 0, left: 0 }
|
||||
if (!this.$viewport) return delta
|
||||
|
||||
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
|
||||
var viewportDimensions = this.getPosition(this.$viewport)
|
||||
|
||||
if (/right|left/.test(placement)) {
|
||||
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
|
||||
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
|
||||
if (topEdgeOffset < viewportDimensions.top) { // top overflow
|
||||
delta.top = viewportDimensions.top - topEdgeOffset
|
||||
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
|
||||
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
|
||||
}
|
||||
} else {
|
||||
var leftEdgeOffset = pos.left - viewportPadding
|
||||
var rightEdgeOffset = pos.left + viewportPadding + actualWidth
|
||||
if (leftEdgeOffset < viewportDimensions.left) { // left overflow
|
||||
delta.left = viewportDimensions.left - leftEdgeOffset
|
||||
} else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
|
||||
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
|
||||
}
|
||||
}
|
||||
|
||||
return delta
|
||||
}
|
||||
|
||||
Tooltip.prototype.getTitle = function () {
|
||||
var title
|
||||
var $e = this.$element
|
||||
var o = this.options
|
||||
|
||||
title = $e.attr('data-original-title')
|
||||
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
|
||||
|
||||
return title
|
||||
}
|
||||
|
||||
Tooltip.prototype.getUID = function (prefix) {
|
||||
do prefix += ~~(Math.random() * 1000000)
|
||||
while (document.getElementById(prefix))
|
||||
return prefix
|
||||
}
|
||||
|
||||
Tooltip.prototype.tip = function () {
|
||||
if (!this.$tip) {
|
||||
this.$tip = $(this.options.template)
|
||||
if (this.$tip.length != 1) {
|
||||
throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
|
||||
}
|
||||
}
|
||||
return this.$tip
|
||||
}
|
||||
|
||||
Tooltip.prototype.arrow = function () {
|
||||
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
|
||||
}
|
||||
|
||||
Tooltip.prototype.enable = function () {
|
||||
this.enabled = true
|
||||
}
|
||||
|
||||
Tooltip.prototype.disable = function () {
|
||||
this.enabled = false
|
||||
}
|
||||
|
||||
Tooltip.prototype.toggleEnabled = function () {
|
||||
this.enabled = !this.enabled
|
||||
}
|
||||
|
||||
Tooltip.prototype.toggle = function (e) {
|
||||
var self = this
|
||||
if (e) {
|
||||
self = $(e.currentTarget).data('bs.' + this.type)
|
||||
if (!self) {
|
||||
self = new this.constructor(e.currentTarget, this.getDelegateOptions())
|
||||
$(e.currentTarget).data('bs.' + this.type, self)
|
||||
}
|
||||
}
|
||||
|
||||
if (e) {
|
||||
self.inState.click = !self.inState.click
|
||||
if (self.isInStateTrue()) self.enter(self)
|
||||
else self.leave(self)
|
||||
} else {
|
||||
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.prototype.destroy = function () {
|
||||
var that = this
|
||||
clearTimeout(this.timeout)
|
||||
this.hide(function () {
|
||||
that.$element.off('.' + that.type).removeData('bs.' + that.type)
|
||||
if (that.$tip) {
|
||||
that.$tip.detach()
|
||||
}
|
||||
that.$tip = null
|
||||
that.$arrow = null
|
||||
that.$viewport = null
|
||||
that.$element = null
|
||||
})
|
||||
}
|
||||
|
||||
Tooltip.prototype.sanitizeHtml = function (unsafeHtml) {
|
||||
return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn)
|
||||
}
|
||||
|
||||
// TOOLTIP PLUGIN DEFINITION
|
||||
// =========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.tooltip')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data && /destroy|hide/.test(option)) return
|
||||
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.tooltip
|
||||
|
||||
$.fn.tooltip = Plugin
|
||||
$.fn.tooltip.Constructor = Tooltip
|
||||
|
||||
|
||||
// TOOLTIP NO CONFLICT
|
||||
// ===================
|
||||
|
||||
$.fn.tooltip.noConflict = function () {
|
||||
$.fn.tooltip = old
|
||||
return this
|
||||
}
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: popover.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#popovers
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// POPOVER PUBLIC CLASS DEFINITION
|
||||
// ===============================
|
||||
|
||||
var Popover = function (element, options) {
|
||||
this.init('popover', element, options)
|
||||
}
|
||||
|
||||
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
|
||||
|
||||
Popover.VERSION = '3.4.1'
|
||||
|
||||
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
|
||||
placement: 'right',
|
||||
trigger: 'click',
|
||||
content: '',
|
||||
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
|
||||
})
|
||||
|
||||
|
||||
// NOTE: POPOVER EXTENDS tooltip.js
|
||||
// ================================
|
||||
|
||||
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
|
||||
|
||||
Popover.prototype.constructor = Popover
|
||||
|
||||
Popover.prototype.getDefaults = function () {
|
||||
return Popover.DEFAULTS
|
||||
}
|
||||
|
||||
Popover.prototype.setContent = function () {
|
||||
var $tip = this.tip()
|
||||
var title = this.getTitle()
|
||||
var content = this.getContent()
|
||||
|
||||
if (this.options.html) {
|
||||
var typeContent = typeof content
|
||||
|
||||
if (this.options.sanitize) {
|
||||
title = this.sanitizeHtml(title)
|
||||
|
||||
if (typeContent === 'string') {
|
||||
content = this.sanitizeHtml(content)
|
||||
}
|
||||
}
|
||||
|
||||
$tip.find('.popover-title').html(title)
|
||||
$tip.find('.popover-content').children().detach().end()[
|
||||
typeContent === 'string' ? 'html' : 'append'
|
||||
](content)
|
||||
} else {
|
||||
$tip.find('.popover-title').text(title)
|
||||
$tip.find('.popover-content').children().detach().end().text(content)
|
||||
}
|
||||
|
||||
$tip.removeClass('fade top bottom left right in')
|
||||
|
||||
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
|
||||
// this manually by checking the contents.
|
||||
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
|
||||
}
|
||||
|
||||
Popover.prototype.hasContent = function () {
|
||||
return this.getTitle() || this.getContent()
|
||||
}
|
||||
|
||||
Popover.prototype.getContent = function () {
|
||||
var $e = this.$element
|
||||
var o = this.options
|
||||
|
||||
return $e.attr('data-content')
|
||||
|| (typeof o.content == 'function' ?
|
||||
o.content.call($e[0]) :
|
||||
o.content)
|
||||
}
|
||||
|
||||
Popover.prototype.arrow = function () {
|
||||
return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
|
||||
}
|
||||
|
||||
|
||||
// POPOVER PLUGIN DEFINITION
|
||||
// =========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.popover')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data && /destroy|hide/.test(option)) return
|
||||
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.popover
|
||||
|
||||
$.fn.popover = Plugin
|
||||
$.fn.popover.Constructor = Popover
|
||||
|
||||
|
||||
// POPOVER NO CONFLICT
|
||||
// ===================
|
||||
|
||||
$.fn.popover.noConflict = function () {
|
||||
$.fn.popover = old
|
||||
return this
|
||||
}
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: scrollspy.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#scrollspy
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// SCROLLSPY CLASS DEFINITION
|
||||
// ==========================
|
||||
|
||||
function ScrollSpy(element, options) {
|
||||
this.$body = $(document.body)
|
||||
this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
|
||||
this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
|
||||
this.selector = (this.options.target || '') + ' .nav li > a'
|
||||
this.offsets = []
|
||||
this.targets = []
|
||||
this.activeTarget = null
|
||||
this.scrollHeight = 0
|
||||
|
||||
this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
|
||||
this.refresh()
|
||||
this.process()
|
||||
}
|
||||
|
||||
ScrollSpy.VERSION = '3.4.1'
|
||||
|
||||
ScrollSpy.DEFAULTS = {
|
||||
offset: 10
|
||||
}
|
||||
|
||||
ScrollSpy.prototype.getScrollHeight = function () {
|
||||
return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
|
||||
}
|
||||
|
||||
ScrollSpy.prototype.refresh = function () {
|
||||
var that = this
|
||||
var offsetMethod = 'offset'
|
||||
var offsetBase = 0
|
||||
|
||||
this.offsets = []
|
||||
this.targets = []
|
||||
this.scrollHeight = this.getScrollHeight()
|
||||
|
||||
if (!$.isWindow(this.$scrollElement[0])) {
|
||||
offsetMethod = 'position'
|
||||
offsetBase = this.$scrollElement.scrollTop()
|
||||
}
|
||||
|
||||
this.$body
|
||||
.find(this.selector)
|
||||
.map(function () {
|
||||
var $el = $(this)
|
||||
var href = $el.data('target') || $el.attr('href')
|
||||
var $href = /^#./.test(href) && $(href)
|
||||
|
||||
return ($href
|
||||
&& $href.length
|
||||
&& $href.is(':visible')
|
||||
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
|
||||
})
|
||||
.sort(function (a, b) { return a[0] - b[0] })
|
||||
.each(function () {
|
||||
that.offsets.push(this[0])
|
||||
that.targets.push(this[1])
|
||||
})
|
||||
}
|
||||
|
||||
ScrollSpy.prototype.process = function () {
|
||||
var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
|
||||
var scrollHeight = this.getScrollHeight()
|
||||
var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
|
||||
var offsets = this.offsets
|
||||
var targets = this.targets
|
||||
var activeTarget = this.activeTarget
|
||||
var i
|
||||
|
||||
if (this.scrollHeight != scrollHeight) {
|
||||
this.refresh()
|
||||
}
|
||||
|
||||
if (scrollTop >= maxScroll) {
|
||||
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
|
||||
}
|
||||
|
||||
if (activeTarget && scrollTop < offsets[0]) {
|
||||
this.activeTarget = null
|
||||
return this.clear()
|
||||
}
|
||||
|
||||
for (i = offsets.length; i--;) {
|
||||
activeTarget != targets[i]
|
||||
&& scrollTop >= offsets[i]
|
||||
&& (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
|
||||
&& this.activate(targets[i])
|
||||
}
|
||||
}
|
||||
|
||||
ScrollSpy.prototype.activate = function (target) {
|
||||
this.activeTarget = target
|
||||
|
||||
this.clear()
|
||||
|
||||
var selector = this.selector +
|
||||
'[data-target="' + target + '"],' +
|
||||
this.selector + '[href="' + target + '"]'
|
||||
|
||||
var active = $(selector)
|
||||
.parents('li')
|
||||
.addClass('active')
|
||||
|
||||
if (active.parent('.dropdown-menu').length) {
|
||||
active = active
|
||||
.closest('li.dropdown')
|
||||
.addClass('active')
|
||||
}
|
||||
|
||||
active.trigger('activate.bs.scrollspy')
|
||||
}
|
||||
|
||||
ScrollSpy.prototype.clear = function () {
|
||||
$(this.selector)
|
||||
.parentsUntil(this.options.target, '.active')
|
||||
.removeClass('active')
|
||||
}
|
||||
|
||||
|
||||
// SCROLLSPY PLUGIN DEFINITION
|
||||
// ===========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.scrollspy')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.scrollspy
|
||||
|
||||
$.fn.scrollspy = Plugin
|
||||
$.fn.scrollspy.Constructor = ScrollSpy
|
||||
|
||||
|
||||
// SCROLLSPY NO CONFLICT
|
||||
// =====================
|
||||
|
||||
$.fn.scrollspy.noConflict = function () {
|
||||
$.fn.scrollspy = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// SCROLLSPY DATA-API
|
||||
// ==================
|
||||
|
||||
$(window).on('load.bs.scrollspy.data-api', function () {
|
||||
$('[data-spy="scroll"]').each(function () {
|
||||
var $spy = $(this)
|
||||
Plugin.call($spy, $spy.data())
|
||||
})
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: tab.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#tabs
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// TAB CLASS DEFINITION
|
||||
// ====================
|
||||
|
||||
var Tab = function (element) {
|
||||
// jscs:disable requireDollarBeforejQueryAssignment
|
||||
this.element = $(element)
|
||||
// jscs:enable requireDollarBeforejQueryAssignment
|
||||
}
|
||||
|
||||
Tab.VERSION = '3.4.1'
|
||||
|
||||
Tab.TRANSITION_DURATION = 150
|
||||
|
||||
Tab.prototype.show = function () {
|
||||
var $this = this.element
|
||||
var $ul = $this.closest('ul:not(.dropdown-menu)')
|
||||
var selector = $this.data('target')
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
||||
}
|
||||
|
||||
if ($this.parent('li').hasClass('active')) return
|
||||
|
||||
var $previous = $ul.find('.active:last a')
|
||||
var hideEvent = $.Event('hide.bs.tab', {
|
||||
relatedTarget: $this[0]
|
||||
})
|
||||
var showEvent = $.Event('show.bs.tab', {
|
||||
relatedTarget: $previous[0]
|
||||
})
|
||||
|
||||
$previous.trigger(hideEvent)
|
||||
$this.trigger(showEvent)
|
||||
|
||||
if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
|
||||
|
||||
var $target = $(document).find(selector)
|
||||
|
||||
this.activate($this.closest('li'), $ul)
|
||||
this.activate($target, $target.parent(), function () {
|
||||
$previous.trigger({
|
||||
type: 'hidden.bs.tab',
|
||||
relatedTarget: $this[0]
|
||||
})
|
||||
$this.trigger({
|
||||
type: 'shown.bs.tab',
|
||||
relatedTarget: $previous[0]
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Tab.prototype.activate = function (element, container, callback) {
|
||||
var $active = container.find('> .active')
|
||||
var transition = callback
|
||||
&& $.support.transition
|
||||
&& ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
|
||||
|
||||
function next() {
|
||||
$active
|
||||
.removeClass('active')
|
||||
.find('> .dropdown-menu > .active')
|
||||
.removeClass('active')
|
||||
.end()
|
||||
.find('[data-toggle="tab"]')
|
||||
.attr('aria-expanded', false)
|
||||
|
||||
element
|
||||
.addClass('active')
|
||||
.find('[data-toggle="tab"]')
|
||||
.attr('aria-expanded', true)
|
||||
|
||||
if (transition) {
|
||||
element[0].offsetWidth // reflow for transition
|
||||
element.addClass('in')
|
||||
} else {
|
||||
element.removeClass('fade')
|
||||
}
|
||||
|
||||
if (element.parent('.dropdown-menu').length) {
|
||||
element
|
||||
.closest('li.dropdown')
|
||||
.addClass('active')
|
||||
.end()
|
||||
.find('[data-toggle="tab"]')
|
||||
.attr('aria-expanded', true)
|
||||
}
|
||||
|
||||
callback && callback()
|
||||
}
|
||||
|
||||
$active.length && transition ?
|
||||
$active
|
||||
.one('bsTransitionEnd', next)
|
||||
.emulateTransitionEnd(Tab.TRANSITION_DURATION) :
|
||||
next()
|
||||
|
||||
$active.removeClass('in')
|
||||
}
|
||||
|
||||
|
||||
// TAB PLUGIN DEFINITION
|
||||
// =====================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.tab')
|
||||
|
||||
if (!data) $this.data('bs.tab', (data = new Tab(this)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.tab
|
||||
|
||||
$.fn.tab = Plugin
|
||||
$.fn.tab.Constructor = Tab
|
||||
|
||||
|
||||
// TAB NO CONFLICT
|
||||
// ===============
|
||||
|
||||
$.fn.tab.noConflict = function () {
|
||||
$.fn.tab = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// TAB DATA-API
|
||||
// ============
|
||||
|
||||
var clickHandler = function (e) {
|
||||
e.preventDefault()
|
||||
Plugin.call($(this), 'show')
|
||||
}
|
||||
|
||||
$(document)
|
||||
.on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
|
||||
.on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: affix.js v3.4.1
|
||||
* https://getbootstrap.com/docs/3.4/javascript/#affix
|
||||
* ========================================================================
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// AFFIX CLASS DEFINITION
|
||||
// ======================
|
||||
|
||||
var Affix = function (element, options) {
|
||||
this.options = $.extend({}, Affix.DEFAULTS, options)
|
||||
|
||||
var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target)
|
||||
|
||||
this.$target = target
|
||||
.on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
|
||||
.on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
|
||||
|
||||
this.$element = $(element)
|
||||
this.affixed = null
|
||||
this.unpin = null
|
||||
this.pinnedOffset = null
|
||||
|
||||
this.checkPosition()
|
||||
}
|
||||
|
||||
Affix.VERSION = '3.4.1'
|
||||
|
||||
Affix.RESET = 'affix affix-top affix-bottom'
|
||||
|
||||
Affix.DEFAULTS = {
|
||||
offset: 0,
|
||||
target: window
|
||||
}
|
||||
|
||||
Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
|
||||
var scrollTop = this.$target.scrollTop()
|
||||
var position = this.$element.offset()
|
||||
var targetHeight = this.$target.height()
|
||||
|
||||
if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
|
||||
|
||||
if (this.affixed == 'bottom') {
|
||||
if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
|
||||
return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
|
||||
}
|
||||
|
||||
var initializing = this.affixed == null
|
||||
var colliderTop = initializing ? scrollTop : position.top
|
||||
var colliderHeight = initializing ? targetHeight : height
|
||||
|
||||
if (offsetTop != null && scrollTop <= offsetTop) return 'top'
|
||||
if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Affix.prototype.getPinnedOffset = function () {
|
||||
if (this.pinnedOffset) return this.pinnedOffset
|
||||
this.$element.removeClass(Affix.RESET).addClass('affix')
|
||||
var scrollTop = this.$target.scrollTop()
|
||||
var position = this.$element.offset()
|
||||
return (this.pinnedOffset = position.top - scrollTop)
|
||||
}
|
||||
|
||||
Affix.prototype.checkPositionWithEventLoop = function () {
|
||||
setTimeout($.proxy(this.checkPosition, this), 1)
|
||||
}
|
||||
|
||||
Affix.prototype.checkPosition = function () {
|
||||
if (!this.$element.is(':visible')) return
|
||||
|
||||
var height = this.$element.height()
|
||||
var offset = this.options.offset
|
||||
var offsetTop = offset.top
|
||||
var offsetBottom = offset.bottom
|
||||
var scrollHeight = Math.max($(document).height(), $(document.body).height())
|
||||
|
||||
if (typeof offset != 'object') offsetBottom = offsetTop = offset
|
||||
if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
|
||||
if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
|
||||
|
||||
var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
|
||||
|
||||
if (this.affixed != affix) {
|
||||
if (this.unpin != null) this.$element.css('top', '')
|
||||
|
||||
var affixType = 'affix' + (affix ? '-' + affix : '')
|
||||
var e = $.Event(affixType + '.bs.affix')
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
this.affixed = affix
|
||||
this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
|
||||
|
||||
this.$element
|
||||
.removeClass(Affix.RESET)
|
||||
.addClass(affixType)
|
||||
.trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
|
||||
}
|
||||
|
||||
if (affix == 'bottom') {
|
||||
this.$element.offset({
|
||||
top: scrollHeight - height - offsetBottom
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// AFFIX PLUGIN DEFINITION
|
||||
// =======================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.affix')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.affix
|
||||
|
||||
$.fn.affix = Plugin
|
||||
$.fn.affix.Constructor = Affix
|
||||
|
||||
|
||||
// AFFIX NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.affix.noConflict = function () {
|
||||
$.fn.affix = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// AFFIX DATA-API
|
||||
// ==============
|
||||
|
||||
$(window).on('load', function () {
|
||||
$('[data-spy="affix"]').each(function () {
|
||||
var $spy = $(this)
|
||||
var data = $spy.data()
|
||||
|
||||
data.offset = data.offset || {}
|
||||
|
||||
if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
|
||||
if (data.offsetTop != null) data.offset.top = data.offsetTop
|
||||
|
||||
Plugin.call($spy, data)
|
||||
})
|
||||
})
|
||||
|
||||
}(jQuery);
|
|
@ -0,0 +1,13 @@
|
|||
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
|
||||
require('../../js/transition.js')
|
||||
require('../../js/alert.js')
|
||||
require('../../js/button.js')
|
||||
require('../../js/carousel.js')
|
||||
require('../../js/collapse.js')
|
||||
require('../../js/dropdown.js')
|
||||
require('../../js/modal.js')
|
||||
require('../../js/tooltip.js')
|
||||
require('../../js/popover.js')
|
||||
require('../../js/scrollspy.js')
|
||||
require('../../js/tab.js')
|
||||
require('../../js/affix.js')
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "jquery-validation-unobtrusive",
|
||||
"homepage": "https://github.com/aspnet/jquery-validation-unobtrusive",
|
||||
"version": "3.2.9",
|
||||
"_release": "3.2.9",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v3.2.9",
|
||||
"commit": "a91f5401898e125f10771c5f5f0909d8c4c82396"
|
||||
},
|
||||
"_source": "https://github.com/aspnet/jquery-validation-unobtrusive.git",
|
||||
"_target": "^3.2.9",
|
||||
"_originalSource": "jquery-validation-unobtrusive",
|
||||
"_direct": true
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
Copyright (c) .NET Foundation. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
these files except in compliance with the License. You may obtain a copy of the
|
||||
License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed
|
||||
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
|
@ -0,0 +1,431 @@
|
|||
// Unobtrusive validation support library for jQuery and jQuery Validate
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// @version v3.2.9
|
||||
|
||||
/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
|
||||
/*global document: false, jQuery: false */
|
||||
|
||||
(function (factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define("jquery.validate.unobtrusive", ['jquery.validation'], factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
// CommonJS-like environments that support module.exports
|
||||
module.exports = factory(require('jquery-validation'));
|
||||
} else {
|
||||
// Browser global
|
||||
jQuery.validator.unobtrusive = factory(jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
var $jQval = $.validator,
|
||||
adapters,
|
||||
data_validation = "unobtrusiveValidation";
|
||||
|
||||
function setValidationValues(options, ruleName, value) {
|
||||
options.rules[ruleName] = value;
|
||||
if (options.message) {
|
||||
options.messages[ruleName] = options.message;
|
||||
}
|
||||
}
|
||||
|
||||
function splitAndTrim(value) {
|
||||
return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
|
||||
}
|
||||
|
||||
function escapeAttributeValue(value) {
|
||||
// As mentioned on http://api.jquery.com/category/selectors/
|
||||
return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
|
||||
}
|
||||
|
||||
function getModelPrefix(fieldName) {
|
||||
return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
|
||||
}
|
||||
|
||||
function appendModelPrefix(value, prefix) {
|
||||
if (value.indexOf("*.") === 0) {
|
||||
value = value.replace("*.", prefix);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function onError(error, inputElement) { // 'this' is the form element
|
||||
var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
|
||||
replaceAttrValue = container.attr("data-valmsg-replace"),
|
||||
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;
|
||||
|
||||
container.removeClass("field-validation-valid").addClass("field-validation-error");
|
||||
error.data("unobtrusiveContainer", container);
|
||||
|
||||
if (replace) {
|
||||
container.empty();
|
||||
error.removeClass("input-validation-error").appendTo(container);
|
||||
}
|
||||
else {
|
||||
error.hide();
|
||||
}
|
||||
}
|
||||
|
||||
function onErrors(event, validator) { // 'this' is the form element
|
||||
var container = $(this).find("[data-valmsg-summary=true]"),
|
||||
list = container.find("ul");
|
||||
|
||||
if (list && list.length && validator.errorList.length) {
|
||||
list.empty();
|
||||
container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
|
||||
|
||||
$.each(validator.errorList, function () {
|
||||
$("<li />").html(this.message).appendTo(list);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onSuccess(error) { // 'this' is the form element
|
||||
var container = error.data("unobtrusiveContainer");
|
||||
|
||||
if (container) {
|
||||
var replaceAttrValue = container.attr("data-valmsg-replace"),
|
||||
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null;
|
||||
|
||||
container.addClass("field-validation-valid").removeClass("field-validation-error");
|
||||
error.removeData("unobtrusiveContainer");
|
||||
|
||||
if (replace) {
|
||||
container.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onReset(event) { // 'this' is the form element
|
||||
var $form = $(this),
|
||||
key = '__jquery_unobtrusive_validation_form_reset';
|
||||
if ($form.data(key)) {
|
||||
return;
|
||||
}
|
||||
// Set a flag that indicates we're currently resetting the form.
|
||||
$form.data(key, true);
|
||||
try {
|
||||
$form.data("validator").resetForm();
|
||||
} finally {
|
||||
$form.removeData(key);
|
||||
}
|
||||
|
||||
$form.find(".validation-summary-errors")
|
||||
.addClass("validation-summary-valid")
|
||||
.removeClass("validation-summary-errors");
|
||||
$form.find(".field-validation-error")
|
||||
.addClass("field-validation-valid")
|
||||
.removeClass("field-validation-error")
|
||||
.removeData("unobtrusiveContainer")
|
||||
.find(">*") // If we were using valmsg-replace, get the underlying error
|
||||
.removeData("unobtrusiveContainer");
|
||||
}
|
||||
|
||||
function validationInfo(form) {
|
||||
var $form = $(form),
|
||||
result = $form.data(data_validation),
|
||||
onResetProxy = $.proxy(onReset, form),
|
||||
defaultOptions = $jQval.unobtrusive.options || {},
|
||||
execInContext = function (name, args) {
|
||||
var func = defaultOptions[name];
|
||||
func && $.isFunction(func) && func.apply(form, args);
|
||||
};
|
||||
|
||||
if (!result) {
|
||||
result = {
|
||||
options: { // options structure passed to jQuery Validate's validate() method
|
||||
errorClass: defaultOptions.errorClass || "input-validation-error",
|
||||
errorElement: defaultOptions.errorElement || "span",
|
||||
errorPlacement: function () {
|
||||
onError.apply(form, arguments);
|
||||
execInContext("errorPlacement", arguments);
|
||||
},
|
||||
invalidHandler: function () {
|
||||
onErrors.apply(form, arguments);
|
||||
execInContext("invalidHandler", arguments);
|
||||
},
|
||||
messages: {},
|
||||
rules: {},
|
||||
success: function () {
|
||||
onSuccess.apply(form, arguments);
|
||||
execInContext("success", arguments);
|
||||
}
|
||||
},
|
||||
attachValidation: function () {
|
||||
$form
|
||||
.off("reset." + data_validation, onResetProxy)
|
||||
.on("reset." + data_validation, onResetProxy)
|
||||
.validate(this.options);
|
||||
},
|
||||
validate: function () { // a validation function that is called by unobtrusive Ajax
|
||||
$form.validate();
|
||||
return $form.valid();
|
||||
}
|
||||
};
|
||||
$form.data(data_validation, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
$jQval.unobtrusive = {
|
||||
adapters: [],
|
||||
|
||||
parseElement: function (element, skipAttach) {
|
||||
/// <summary>
|
||||
/// Parses a single HTML element for unobtrusive validation attributes.
|
||||
/// </summary>
|
||||
/// <param name="element" domElement="true">The HTML element to be parsed.</param>
|
||||
/// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
|
||||
/// validation to the form. If parsing just this single element, you should specify true.
|
||||
/// If parsing several elements, you should specify false, and manually attach the validation
|
||||
/// to the form when you are finished. The default is false.</param>
|
||||
var $element = $(element),
|
||||
form = $element.parents("form")[0],
|
||||
valInfo, rules, messages;
|
||||
|
||||
if (!form) { // Cannot do client-side validation without a form
|
||||
return;
|
||||
}
|
||||
|
||||
valInfo = validationInfo(form);
|
||||
valInfo.options.rules[element.name] = rules = {};
|
||||
valInfo.options.messages[element.name] = messages = {};
|
||||
|
||||
$.each(this.adapters, function () {
|
||||
var prefix = "data-val-" + this.name,
|
||||
message = $element.attr(prefix),
|
||||
paramValues = {};
|
||||
|
||||
if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy)
|
||||
prefix += "-";
|
||||
|
||||
$.each(this.params, function () {
|
||||
paramValues[this] = $element.attr(prefix + this);
|
||||
});
|
||||
|
||||
this.adapt({
|
||||
element: element,
|
||||
form: form,
|
||||
message: message,
|
||||
params: paramValues,
|
||||
rules: rules,
|
||||
messages: messages
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$.extend(rules, { "__dummy__": true });
|
||||
|
||||
if (!skipAttach) {
|
||||
valInfo.attachValidation();
|
||||
}
|
||||
},
|
||||
|
||||
parse: function (selector) {
|
||||
/// <summary>
|
||||
/// Parses all the HTML elements in the specified selector. It looks for input elements decorated
|
||||
/// with the [data-val=true] attribute value and enables validation according to the data-val-*
|
||||
/// attribute values.
|
||||
/// </summary>
|
||||
/// <param name="selector" type="String">Any valid jQuery selector.</param>
|
||||
|
||||
// $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one
|
||||
// element with data-val=true
|
||||
var $selector = $(selector),
|
||||
$forms = $selector.parents()
|
||||
.addBack()
|
||||
.filter("form")
|
||||
.add($selector.find("form"))
|
||||
.has("[data-val=true]");
|
||||
|
||||
$selector.find("[data-val=true]").each(function () {
|
||||
$jQval.unobtrusive.parseElement(this, true);
|
||||
});
|
||||
|
||||
$forms.each(function () {
|
||||
var info = validationInfo(this);
|
||||
if (info) {
|
||||
info.attachValidation();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
adapters = $jQval.unobtrusive.adapters;
|
||||
|
||||
adapters.add = function (adapterName, params, fn) {
|
||||
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
|
||||
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
|
||||
/// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
|
||||
/// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
|
||||
/// mmmm is the parameter name).</param>
|
||||
/// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
|
||||
/// attributes into jQuery Validate rules and/or messages.</param>
|
||||
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
if (!fn) { // Called with no params, just a function
|
||||
fn = params;
|
||||
params = [];
|
||||
}
|
||||
this.push({ name: adapterName, params: params, adapt: fn });
|
||||
return this;
|
||||
};
|
||||
|
||||
adapters.addBool = function (adapterName, ruleName) {
|
||||
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
|
||||
/// the jQuery Validate validation rule has no parameter values.</summary>
|
||||
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
|
||||
/// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
|
||||
/// of adapterName will be used instead.</param>
|
||||
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
return this.add(adapterName, function (options) {
|
||||
setValidationValues(options, ruleName || adapterName, true);
|
||||
});
|
||||
};
|
||||
|
||||
adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
|
||||
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
|
||||
/// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
|
||||
/// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
|
||||
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
/// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
|
||||
/// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
|
||||
/// have a minimum value.</param>
|
||||
/// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
|
||||
/// have a maximum value.</param>
|
||||
/// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
|
||||
/// have both a minimum and maximum value.</param>
|
||||
/// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
|
||||
/// contains the minimum value. The default is "min".</param>
|
||||
/// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
|
||||
/// contains the maximum value. The default is "max".</param>
|
||||
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
|
||||
var min = options.params.min,
|
||||
max = options.params.max;
|
||||
|
||||
if (min && max) {
|
||||
setValidationValues(options, minMaxRuleName, [min, max]);
|
||||
}
|
||||
else if (min) {
|
||||
setValidationValues(options, minRuleName, min);
|
||||
}
|
||||
else if (max) {
|
||||
setValidationValues(options, maxRuleName, max);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
adapters.addSingleVal = function (adapterName, attribute, ruleName) {
|
||||
/// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
|
||||
/// the jQuery Validate validation rule has a single value.</summary>
|
||||
/// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
|
||||
/// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
|
||||
/// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
|
||||
/// The default is "val".</param>
|
||||
/// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
|
||||
/// of adapterName will be used instead.</param>
|
||||
/// <returns type="jQuery.validator.unobtrusive.adapters" />
|
||||
return this.add(adapterName, [attribute || "val"], function (options) {
|
||||
setValidationValues(options, ruleName || adapterName, options.params[attribute]);
|
||||
});
|
||||
};
|
||||
|
||||
$jQval.addMethod("__dummy__", function (value, element, params) {
|
||||
return true;
|
||||
});
|
||||
|
||||
$jQval.addMethod("regex", function (value, element, params) {
|
||||
var match;
|
||||
if (this.optional(element)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
match = new RegExp(params).exec(value);
|
||||
return (match && (match.index === 0) && (match[0].length === value.length));
|
||||
});
|
||||
|
||||
$jQval.addMethod("nonalphamin", function (value, element, nonalphamin) {
|
||||
var match;
|
||||
if (nonalphamin) {
|
||||
match = value.match(/\W/g);
|
||||
match = match && match.length >= nonalphamin;
|
||||
}
|
||||
return match;
|
||||
});
|
||||
|
||||
if ($jQval.methods.extension) {
|
||||
adapters.addSingleVal("accept", "mimtype");
|
||||
adapters.addSingleVal("extension", "extension");
|
||||
} else {
|
||||
// for backward compatibility, when the 'extension' validation method does not exist, such as with versions
|
||||
// of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for
|
||||
// validating the extension, and ignore mime-type validations as they are not supported.
|
||||
adapters.addSingleVal("extension", "extension", "accept");
|
||||
}
|
||||
|
||||
adapters.addSingleVal("regex", "pattern");
|
||||
adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
|
||||
adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
|
||||
adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength");
|
||||
adapters.add("equalto", ["other"], function (options) {
|
||||
var prefix = getModelPrefix(options.element.name),
|
||||
other = options.params.other,
|
||||
fullOtherName = appendModelPrefix(other, prefix),
|
||||
element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0];
|
||||
|
||||
setValidationValues(options, "equalTo", element);
|
||||
});
|
||||
adapters.add("required", function (options) {
|
||||
// jQuery Validate equates "required" with "mandatory" for checkbox elements
|
||||
if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
|
||||
setValidationValues(options, "required", true);
|
||||
}
|
||||
});
|
||||
adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
|
||||
var value = {
|
||||
url: options.params.url,
|
||||
type: options.params.type || "GET",
|
||||
data: {}
|
||||
},
|
||||
prefix = getModelPrefix(options.element.name);
|
||||
|
||||
$.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
|
||||
var paramName = appendModelPrefix(fieldName, prefix);
|
||||
value.data[paramName] = function () {
|
||||
var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']");
|
||||
// For checkboxes and radio buttons, only pick up values from checked fields.
|
||||
if (field.is(":checkbox")) {
|
||||
return field.filter(":checked").val() || field.filter(":hidden").val() || '';
|
||||
}
|
||||
else if (field.is(":radio")) {
|
||||
return field.filter(":checked").val() || '';
|
||||
}
|
||||
return field.val();
|
||||
};
|
||||
});
|
||||
|
||||
setValidationValues(options, "remote", value);
|
||||
});
|
||||
adapters.add("password", ["min", "nonalphamin", "regex"], function (options) {
|
||||
if (options.params.min) {
|
||||
setValidationValues(options, "minlength", options.params.min);
|
||||
}
|
||||
if (options.params.nonalphamin) {
|
||||
setValidationValues(options, "nonalphamin", options.params.nonalphamin);
|
||||
}
|
||||
if (options.params.regex) {
|
||||
setValidationValues(options, "regex", options.params.regex);
|
||||
}
|
||||
});
|
||||
adapters.add("fileextensions", ["extensions"], function (options) {
|
||||
setValidationValues(options, "extension", options.params.extensions);
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$jQval.unobtrusive.parse(document);
|
||||
});
|
||||
|
||||
return $jQval.unobtrusive;
|
||||
}));
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "jquery-validation",
|
||||
"homepage": "https://jqueryvalidation.org/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/jquery-validation/jquery-validation.git"
|
||||
},
|
||||
"authors": [
|
||||
"Jörn Zaefferer <joern.zaefferer@gmail.com>"
|
||||
],
|
||||
"description": "Form validation made easy",
|
||||
"main": "dist/jquery.validate.js",
|
||||
"keywords": [
|
||||
"forms",
|
||||
"validation",
|
||||
"validate"
|
||||
],
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"demo",
|
||||
"lib"
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": ">= 1.7.2"
|
||||
},
|
||||
"version": "1.17.0",
|
||||
"_release": "1.17.0",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.17.0",
|
||||
"commit": "fc9b12d3bfaa2d0c04605855b896edb2934c0772"
|
||||
},
|
||||
"_source": "https://github.com/jzaefferer/jquery-validation.git",
|
||||
"_target": "^1.17.0",
|
||||
"_originalSource": "jquery-validation",
|
||||
"_direct": true
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
=====================
|
||||
|
||||
Copyright Jörn Zaefferer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -0,0 +1,1601 @@
|
|||
/*!
|
||||
* jQuery Validation Plugin v1.17.0
|
||||
*
|
||||
* https://jqueryvalidation.org/
|
||||
*
|
||||
* Copyright (c) 2017 Jörn Zaefferer
|
||||
* Released under the MIT license
|
||||
*/
|
||||
(function( factory ) {
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
define( ["jquery"], factory );
|
||||
} else if (typeof module === "object" && module.exports) {
|
||||
module.exports = factory( require( "jquery" ) );
|
||||
} else {
|
||||
factory( jQuery );
|
||||
}
|
||||
}(function( $ ) {
|
||||
|
||||
$.extend( $.fn, {
|
||||
|
||||
// https://jqueryvalidation.org/validate/
|
||||
validate: function( options ) {
|
||||
|
||||
// If nothing is selected, return nothing; can't chain anyway
|
||||
if ( !this.length ) {
|
||||
if ( options && options.debug && window.console ) {
|
||||
console.warn( "Nothing selected, can't validate, returning nothing." );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if a validator for this form was already created
|
||||
var validator = $.data( this[ 0 ], "validator" );
|
||||
if ( validator ) {
|
||||
return validator;
|
||||
}
|
||||
|
||||
// Add novalidate tag if HTML5.
|
||||
this.attr( "novalidate", "novalidate" );
|
||||
|
||||
validator = new $.validator( options, this[ 0 ] );
|
||||
$.data( this[ 0 ], "validator", validator );
|
||||
|
||||
if ( validator.settings.onsubmit ) {
|
||||
|
||||
this.on( "click.validate", ":submit", function( event ) {
|
||||
|
||||
// Track the used submit button to properly handle scripted
|
||||
// submits later.
|
||||
validator.submitButton = event.currentTarget;
|
||||
|
||||
// Allow suppressing validation by adding a cancel class to the submit button
|
||||
if ( $( this ).hasClass( "cancel" ) ) {
|
||||
validator.cancelSubmit = true;
|
||||
}
|
||||
|
||||
// Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
|
||||
if ( $( this ).attr( "formnovalidate" ) !== undefined ) {
|
||||
validator.cancelSubmit = true;
|
||||
}
|
||||
} );
|
||||
|
||||
// Validate the form on submit
|
||||
this.on( "submit.validate", function( event ) {
|
||||
if ( validator.settings.debug ) {
|
||||
|
||||
// Prevent form submit to be able to see console output
|
||||
event.preventDefault();
|
||||
}
|
||||
function handle() {
|
||||
var hidden, result;
|
||||
|
||||
// Insert a hidden input as a replacement for the missing submit button
|
||||
// The hidden input is inserted in two cases:
|
||||
// - A user defined a `submitHandler`
|
||||
// - There was a pending request due to `remote` method and `stopRequest()`
|
||||
// was called to submit the form in case it's valid
|
||||
if ( validator.submitButton && ( validator.settings.submitHandler || validator.formSubmitted ) ) {
|
||||
hidden = $( "<input type='hidden'/>" )
|
||||
.attr( "name", validator.submitButton.name )
|
||||
.val( $( validator.submitButton ).val() )
|
||||
.appendTo( validator.currentForm );
|
||||
}
|
||||
|
||||
if ( validator.settings.submitHandler ) {
|
||||
result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
|
||||
if ( hidden ) {
|
||||
|
||||
// And clean up afterwards; thanks to no-block-scope, hidden can be referenced
|
||||
hidden.remove();
|
||||
}
|
||||
if ( result !== undefined ) {
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Prevent submit for invalid forms or custom submit handlers
|
||||
if ( validator.cancelSubmit ) {
|
||||
validator.cancelSubmit = false;
|
||||
return handle();
|
||||
}
|
||||
if ( validator.form() ) {
|
||||
if ( validator.pendingRequest ) {
|
||||
validator.formSubmitted = true;
|
||||
return false;
|
||||
}
|
||||
return handle();
|
||||
} else {
|
||||
validator.focusInvalid();
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
return validator;
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/valid/
|
||||
valid: function() {
|
||||
var valid, validator, errorList;
|
||||
|
||||
if ( $( this[ 0 ] ).is( "form" ) ) {
|
||||
valid = this.validate().form();
|
||||
} else {
|
||||
errorList = [];
|
||||
valid = true;
|
||||
validator = $( this[ 0 ].form ).validate();
|
||||
this.each( function() {
|
||||
valid = validator.element( this ) && valid;
|
||||
if ( !valid ) {
|
||||
errorList = errorList.concat( validator.errorList );
|
||||
}
|
||||
} );
|
||||
validator.errorList = errorList;
|
||||
}
|
||||
return valid;
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/rules/
|
||||
rules: function( command, argument ) {
|
||||
var element = this[ 0 ],
|
||||
settings, staticRules, existingRules, data, param, filtered;
|
||||
|
||||
// If nothing is selected, return empty object; can't chain anyway
|
||||
if ( element == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !element.form && element.hasAttribute( "contenteditable" ) ) {
|
||||
element.form = this.closest( "form" )[ 0 ];
|
||||
element.name = this.attr( "name" );
|
||||
}
|
||||
|
||||
if ( element.form == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( command ) {
|
||||
settings = $.data( element.form, "validator" ).settings;
|
||||
staticRules = settings.rules;
|
||||
existingRules = $.validator.staticRules( element );
|
||||
switch ( command ) {
|
||||
case "add":
|
||||
$.extend( existingRules, $.validator.normalizeRule( argument ) );
|
||||
|
||||
// Remove messages from rules, but allow them to be set separately
|
||||
delete existingRules.messages;
|
||||
staticRules[ element.name ] = existingRules;
|
||||
if ( argument.messages ) {
|
||||
settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );
|
||||
}
|
||||
break;
|
||||
case "remove":
|
||||
if ( !argument ) {
|
||||
delete staticRules[ element.name ];
|
||||
return existingRules;
|
||||
}
|
||||
filtered = {};
|
||||
$.each( argument.split( /\s/ ), function( index, method ) {
|
||||
filtered[ method ] = existingRules[ method ];
|
||||
delete existingRules[ method ];
|
||||
} );
|
||||
return filtered;
|
||||
}
|
||||
}
|
||||
|
||||
data = $.validator.normalizeRules(
|
||||
$.extend(
|
||||
{},
|
||||
$.validator.classRules( element ),
|
||||
$.validator.attributeRules( element ),
|
||||
$.validator.dataRules( element ),
|
||||
$.validator.staticRules( element )
|
||||
), element );
|
||||
|
||||
// Make sure required is at front
|
||||
if ( data.required ) {
|
||||
param = data.required;
|
||||
delete data.required;
|
||||
data = $.extend( { required: param }, data );
|
||||
}
|
||||
|
||||
// Make sure remote is at back
|
||||
if ( data.remote ) {
|
||||
param = data.remote;
|
||||
delete data.remote;
|
||||
data = $.extend( data, { remote: param } );
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
} );
|
||||
|
||||
// Custom selectors
|
||||
$.extend( $.expr.pseudos || $.expr[ ":" ], { // '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support
|
||||
|
||||
// https://jqueryvalidation.org/blank-selector/
|
||||
blank: function( a ) {
|
||||
return !$.trim( "" + $( a ).val() );
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/filled-selector/
|
||||
filled: function( a ) {
|
||||
var val = $( a ).val();
|
||||
return val !== null && !!$.trim( "" + val );
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/unchecked-selector/
|
||||
unchecked: function( a ) {
|
||||
return !$( a ).prop( "checked" );
|
||||
}
|
||||
} );
|
||||
|
||||
// Constructor for validator
|
||||
$.validator = function( options, form ) {
|
||||
this.settings = $.extend( true, {}, $.validator.defaults, options );
|
||||
this.currentForm = form;
|
||||
this.init();
|
||||
};
|
||||
|
||||
// https://jqueryvalidation.org/jQuery.validator.format/
|
||||
$.validator.format = function( source, params ) {
|
||||
if ( arguments.length === 1 ) {
|
||||
return function() {
|
||||
var args = $.makeArray( arguments );
|
||||
args.unshift( source );
|
||||
return $.validator.format.apply( this, args );
|
||||
};
|
||||
}
|
||||
if ( params === undefined ) {
|
||||
return source;
|
||||
}
|
||||
if ( arguments.length > 2 && params.constructor !== Array ) {
|
||||
params = $.makeArray( arguments ).slice( 1 );
|
||||
}
|
||||
if ( params.constructor !== Array ) {
|
||||
params = [ params ];
|
||||
}
|
||||
$.each( params, function( i, n ) {
|
||||
source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
|
||||
return n;
|
||||
} );
|
||||
} );
|
||||
return source;
|
||||
};
|
||||
|
||||
$.extend( $.validator, {
|
||||
|
||||
defaults: {
|
||||
messages: {},
|
||||
groups: {},
|
||||
rules: {},
|
||||
errorClass: "error",
|
||||
pendingClass: "pending",
|
||||
validClass: "valid",
|
||||
errorElement: "label",
|
||||
focusCleanup: false,
|
||||
focusInvalid: true,
|
||||
errorContainer: $( [] ),
|
||||
errorLabelContainer: $( [] ),
|
||||
onsubmit: true,
|
||||
ignore: ":hidden",
|
||||
ignoreTitle: false,
|
||||
onfocusin: function( element ) {
|
||||
this.lastActive = element;
|
||||
|
||||
// Hide error label and remove error class on focus if enabled
|
||||
if ( this.settings.focusCleanup ) {
|
||||
if ( this.settings.unhighlight ) {
|
||||
this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
|
||||
}
|
||||
this.hideThese( this.errorsFor( element ) );
|
||||
}
|
||||
},
|
||||
onfocusout: function( element ) {
|
||||
if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
|
||||
this.element( element );
|
||||
}
|
||||
},
|
||||
onkeyup: function( element, event ) {
|
||||
|
||||
// Avoid revalidate the field when pressing one of the following keys
|
||||
// Shift => 16
|
||||
// Ctrl => 17
|
||||
// Alt => 18
|
||||
// Caps lock => 20
|
||||
// End => 35
|
||||
// Home => 36
|
||||
// Left arrow => 37
|
||||
// Up arrow => 38
|
||||
// Right arrow => 39
|
||||
// Down arrow => 40
|
||||
// Insert => 45
|
||||
// Num lock => 144
|
||||
// AltGr key => 225
|
||||
var excludedKeys = [
|
||||
16, 17, 18, 20, 35, 36, 37,
|
||||
38, 39, 40, 45, 144, 225
|
||||
];
|
||||
|
||||
if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {
|
||||
return;
|
||||
} else if ( element.name in this.submitted || element.name in this.invalid ) {
|
||||
this.element( element );
|
||||
}
|
||||
},
|
||||
onclick: function( element ) {
|
||||
|
||||
// Click on selects, radiobuttons and checkboxes
|
||||
if ( element.name in this.submitted ) {
|
||||
this.element( element );
|
||||
|
||||
// Or option elements, check parent select in that case
|
||||
} else if ( element.parentNode.name in this.submitted ) {
|
||||
this.element( element.parentNode );
|
||||
}
|
||||
},
|
||||
highlight: function( element, errorClass, validClass ) {
|
||||
if ( element.type === "radio" ) {
|
||||
this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
|
||||
} else {
|
||||
$( element ).addClass( errorClass ).removeClass( validClass );
|
||||
}
|
||||
},
|
||||
unhighlight: function( element, errorClass, validClass ) {
|
||||
if ( element.type === "radio" ) {
|
||||
this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
|
||||
} else {
|
||||
$( element ).removeClass( errorClass ).addClass( validClass );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/jQuery.validator.setDefaults/
|
||||
setDefaults: function( settings ) {
|
||||
$.extend( $.validator.defaults, settings );
|
||||
},
|
||||
|
||||
messages: {
|
||||
required: "This field is required.",
|
||||
remote: "Please fix this field.",
|
||||
email: "Please enter a valid email address.",
|
||||
url: "Please enter a valid URL.",
|
||||
date: "Please enter a valid date.",
|
||||
dateISO: "Please enter a valid date (ISO).",
|
||||
number: "Please enter a valid number.",
|
||||
digits: "Please enter only digits.",
|
||||
equalTo: "Please enter the same value again.",
|
||||
maxlength: $.validator.format( "Please enter no more than {0} characters." ),
|
||||
minlength: $.validator.format( "Please enter at least {0} characters." ),
|
||||
rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
|
||||
range: $.validator.format( "Please enter a value between {0} and {1}." ),
|
||||
max: $.validator.format( "Please enter a value less than or equal to {0}." ),
|
||||
min: $.validator.format( "Please enter a value greater than or equal to {0}." ),
|
||||
step: $.validator.format( "Please enter a multiple of {0}." )
|
||||
},
|
||||
|
||||
autoCreateRanges: false,
|
||||
|
||||
prototype: {
|
||||
|
||||
init: function() {
|
||||
this.labelContainer = $( this.settings.errorLabelContainer );
|
||||
this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
|
||||
this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
|
||||
this.submitted = {};
|
||||
this.valueCache = {};
|
||||
this.pendingRequest = 0;
|
||||
this.pending = {};
|
||||
this.invalid = {};
|
||||
this.reset();
|
||||
|
||||
var groups = ( this.groups = {} ),
|
||||
rules;
|
||||
$.each( this.settings.groups, function( key, value ) {
|
||||
if ( typeof value === "string" ) {
|
||||
value = value.split( /\s/ );
|
||||
}
|
||||
$.each( value, function( index, name ) {
|
||||
groups[ name ] = key;
|
||||
} );
|
||||
} );
|
||||
rules = this.settings.rules;
|
||||
$.each( rules, function( key, value ) {
|
||||
rules[ key ] = $.validator.normalizeRule( value );
|
||||
} );
|
||||
|
||||
function delegate( event ) {
|
||||
|
||||
// Set form expando on contenteditable
|
||||
if ( !this.form && this.hasAttribute( "contenteditable" ) ) {
|
||||
this.form = $( this ).closest( "form" )[ 0 ];
|
||||
this.name = $( this ).attr( "name" );
|
||||
}
|
||||
|
||||
var validator = $.data( this.form, "validator" ),
|
||||
eventType = "on" + event.type.replace( /^validate/, "" ),
|
||||
settings = validator.settings;
|
||||
if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {
|
||||
settings[ eventType ].call( validator, this, event );
|
||||
}
|
||||
}
|
||||
|
||||
$( this.currentForm )
|
||||
.on( "focusin.validate focusout.validate keyup.validate",
|
||||
":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " +
|
||||
"[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " +
|
||||
"[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " +
|
||||
"[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate )
|
||||
|
||||
// Support: Chrome, oldIE
|
||||
// "select" is provided as event.target when clicking a option
|
||||
.on( "click.validate", "select, option, [type='radio'], [type='checkbox']", delegate );
|
||||
|
||||
if ( this.settings.invalidHandler ) {
|
||||
$( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler );
|
||||
}
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/Validator.form/
|
||||
form: function() {
|
||||
this.checkForm();
|
||||
$.extend( this.submitted, this.errorMap );
|
||||
this.invalid = $.extend( {}, this.errorMap );
|
||||
if ( !this.valid() ) {
|
||||
$( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
|
||||
}
|
||||
this.showErrors();
|
||||
return this.valid();
|
||||
},
|
||||
|
||||
checkForm: function() {
|
||||
this.prepareForm();
|
||||
for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
|
||||
this.check( elements[ i ] );
|
||||
}
|
||||
return this.valid();
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/Validator.element/
|
||||
element: function( element ) {
|
||||
var cleanElement = this.clean( element ),
|
||||
checkElement = this.validationTargetFor( cleanElement ),
|
||||
v = this,
|
||||
result = true,
|
||||
rs, group;
|
||||
|
||||
if ( checkElement === undefined ) {
|
||||
delete this.invalid[ cleanElement.name ];
|
||||
} else {
|
||||
this.prepareElement( checkElement );
|
||||
this.currentElements = $( checkElement );
|
||||
|
||||
// If this element is grouped, then validate all group elements already
|
||||
// containing a value
|
||||
group = this.groups[ checkElement.name ];
|
||||
if ( group ) {
|
||||
$.each( this.groups, function( name, testgroup ) {
|
||||
if ( testgroup === group && name !== checkElement.name ) {
|
||||
cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) );
|
||||
if ( cleanElement && cleanElement.name in v.invalid ) {
|
||||
v.currentElements.push( cleanElement );
|
||||
result = v.check( cleanElement ) && result;
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
rs = this.check( checkElement ) !== false;
|
||||
result = result && rs;
|
||||
if ( rs ) {
|
||||
this.invalid[ checkElement.name ] = false;
|
||||
} else {
|
||||
this.invalid[ checkElement.name ] = true;
|
||||
}
|
||||
|
||||
if ( !this.numberOfInvalids() ) {
|
||||
|
||||
// Hide error containers on last error
|
||||
this.toHide = this.toHide.add( this.containers );
|
||||
}
|
||||
this.showErrors();
|
||||
|
||||
// Add aria-invalid status for screen readers
|
||||
$( element ).attr( "aria-invalid", !rs );
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/Validator.showErrors/
|
||||
showErrors: function( errors ) {
|
||||
if ( errors ) {
|
||||
var validator = this;
|
||||
|
||||
// Add items to error list and map
|
||||
$.extend( this.errorMap, errors );
|
||||
this.errorList = $.map( this.errorMap, function( message, name ) {
|
||||
return {
|
||||
message: message,
|
||||
element: validator.findByName( name )[ 0 ]
|
||||
};
|
||||
} );
|
||||
|
||||
// Remove items from success list
|
||||
this.successList = $.grep( this.successList, function( element ) {
|
||||
return !( element.name in errors );
|
||||
} );
|
||||
}
|
||||
if ( this.settings.showErrors ) {
|
||||
this.settings.showErrors.call( this, this.errorMap, this.errorList );
|
||||
} else {
|
||||
this.defaultShowErrors();
|
||||
}
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/Validator.resetForm/
|
||||
resetForm: function() {
|
||||
if ( $.fn.resetForm ) {
|
||||
$( this.currentForm ).resetForm();
|
||||
}
|
||||
this.invalid = {};
|
||||
this.submitted = {};
|
||||
this.prepareForm();
|
||||
this.hideErrors();
|
||||
var elements = this.elements()
|
||||
.removeData( "previousValue" )
|
||||
.removeAttr( "aria-invalid" );
|
||||
|
||||
this.resetElements( elements );
|
||||
},
|
||||
|
||||
resetElements: function( elements ) {
|
||||
var i;
|
||||
|
||||
if ( this.settings.unhighlight ) {
|
||||
for ( i = 0; elements[ i ]; i++ ) {
|
||||
this.settings.unhighlight.call( this, elements[ i ],
|
||||
this.settings.errorClass, "" );
|
||||
this.findByName( elements[ i ].name ).removeClass( this.settings.validClass );
|
||||
}
|
||||
} else {
|
||||
elements
|
||||
.removeClass( this.settings.errorClass )
|
||||
.removeClass( this.settings.validClass );
|
||||
}
|
||||
},
|
||||
|
||||
numberOfInvalids: function() {
|
||||
return this.objectLength( this.invalid );
|
||||
},
|
||||
|
||||
objectLength: function( obj ) {
|
||||
/* jshint unused: false */
|
||||
var count = 0,
|
||||
i;
|
||||
for ( i in obj ) {
|
||||
|
||||
// This check allows counting elements with empty error
|
||||
// message as invalid elements
|
||||
if ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
},
|
||||
|
||||
hideErrors: function() {
|
||||
this.hideThese( this.toHide );
|
||||
},
|
||||
|
||||
hideThese: function( errors ) {
|
||||
errors.not( this.containers ).text( "" );
|
||||
this.addWrapper( errors ).hide();
|
||||
},
|
||||
|
||||
valid: function() {
|
||||
return this.size() === 0;
|
||||
},
|
||||
|
||||
size: function() {
|
||||
return this.errorList.length;
|
||||
},
|
||||
|
||||
focusInvalid: function() {
|
||||
if ( this.settings.focusInvalid ) {
|
||||
try {
|
||||
$( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] )
|
||||
.filter( ":visible" )
|
||||
.focus()
|
||||
|
||||
// Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
|
||||
.trigger( "focusin" );
|
||||
} catch ( e ) {
|
||||
|
||||
// Ignore IE throwing errors when focusing hidden elements
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
findLastActive: function() {
|
||||
var lastActive = this.lastActive;
|
||||
return lastActive && $.grep( this.errorList, function( n ) {
|
||||
return n.element.name === lastActive.name;
|
||||
} ).length === 1 && lastActive;
|
||||
},
|
||||
|
||||
elements: function() {
|
||||
var validator = this,
|
||||
rulesCache = {};
|
||||
|
||||
// Select all valid inputs inside the form (no submit or reset buttons)
|
||||
return $( this.currentForm )
|
||||
.find( "input, select, textarea, [contenteditable]" )
|
||||
.not( ":submit, :reset, :image, :disabled" )
|
||||
.not( this.settings.ignore )
|
||||
.filter( function() {
|
||||
var name = this.name || $( this ).attr( "name" ); // For contenteditable
|
||||
if ( !name && validator.settings.debug && window.console ) {
|
||||
console.error( "%o has no name assigned", this );
|
||||
}
|
||||
|
||||
// Set form expando on contenteditable
|
||||
if ( this.hasAttribute( "contenteditable" ) ) {
|
||||
this.form = $( this ).closest( "form" )[ 0 ];
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
// Select only the first element for each name, and only those with rules specified
|
||||
if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rulesCache[ name ] = true;
|
||||
return true;
|
||||
} );
|
||||
},
|
||||
|
||||
clean: function( selector ) {
|
||||
return $( selector )[ 0 ];
|
||||
},
|
||||
|
||||
errors: function() {
|
||||
var errorClass = this.settings.errorClass.split( " " ).join( "." );
|
||||
return $( this.settings.errorElement + "." + errorClass, this.errorContext );
|
||||
},
|
||||
|
||||
resetInternals: function() {
|
||||
this.successList = [];
|
||||
this.errorList = [];
|
||||
this.errorMap = {};
|
||||
this.toShow = $( [] );
|
||||
this.toHide = $( [] );
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this.resetInternals();
|
||||
this.currentElements = $( [] );
|
||||
},
|
||||
|
||||
prepareForm: function() {
|
||||
this.reset();
|
||||
this.toHide = this.errors().add( this.containers );
|
||||
},
|
||||
|
||||
prepareElement: function( element ) {
|
||||
this.reset();
|
||||
this.toHide = this.errorsFor( element );
|
||||
},
|
||||
|
||||
elementValue: function( element ) {
|
||||
var $element = $( element ),
|
||||
type = element.type,
|
||||
val, idx;
|
||||
|
||||
if ( type === "radio" || type === "checkbox" ) {
|
||||
return this.findByName( element.name ).filter( ":checked" ).val();
|
||||
} else if ( type === "number" && typeof element.validity !== "undefined" ) {
|
||||
return element.validity.badInput ? "NaN" : $element.val();
|
||||
}
|
||||
|
||||
if ( element.hasAttribute( "contenteditable" ) ) {
|
||||
val = $element.text();
|
||||
} else {
|
||||
val = $element.val();
|
||||
}
|
||||
|
||||
if ( type === "file" ) {
|
||||
|
||||
// Modern browser (chrome & safari)
|
||||
if ( val.substr( 0, 12 ) === "C:\\fakepath\\" ) {
|
||||
return val.substr( 12 );
|
||||
}
|
||||
|
||||
// Legacy browsers
|
||||
// Unix-based path
|
||||
idx = val.lastIndexOf( "/" );
|
||||
if ( idx >= 0 ) {
|
||||
return val.substr( idx + 1 );
|
||||
}
|
||||
|
||||
// Windows-based path
|
||||
idx = val.lastIndexOf( "\\" );
|
||||
if ( idx >= 0 ) {
|
||||
return val.substr( idx + 1 );
|
||||
}
|
||||
|
||||
// Just the file name
|
||||
return val;
|
||||
}
|
||||
|
||||
if ( typeof val === "string" ) {
|
||||
return val.replace( /\r/g, "" );
|
||||
}
|
||||
return val;
|
||||
},
|
||||
|
||||
check: function( element ) {
|
||||
element = this.validationTargetFor( this.clean( element ) );
|
||||
|
||||
var rules = $( element ).rules(),
|
||||
rulesCount = $.map( rules, function( n, i ) {
|
||||
return i;
|
||||
} ).length,
|
||||
dependencyMismatch = false,
|
||||
val = this.elementValue( element ),
|
||||
result, method, rule, normalizer;
|
||||
|
||||
// Prioritize the local normalizer defined for this element over the global one
|
||||
// if the former exists, otherwise user the global one in case it exists.
|
||||
if ( typeof rules.normalizer === "function" ) {
|
||||
normalizer = rules.normalizer;
|
||||
} else if ( typeof this.settings.normalizer === "function" ) {
|
||||
normalizer = this.settings.normalizer;
|
||||
}
|
||||
|
||||
// If normalizer is defined, then call it to retreive the changed value instead
|
||||
// of using the real one.
|
||||
// Note that `this` in the normalizer is `element`.
|
||||
if ( normalizer ) {
|
||||
val = normalizer.call( element, val );
|
||||
|
||||
if ( typeof val !== "string" ) {
|
||||
throw new TypeError( "The normalizer should return a string value." );
|
||||
}
|
||||
|
||||
// Delete the normalizer from rules to avoid treating it as a pre-defined method.
|
||||
delete rules.normalizer;
|
||||
}
|
||||
|
||||
for ( method in rules ) {
|
||||
rule = { method: method, parameters: rules[ method ] };
|
||||
try {
|
||||
result = $.validator.methods[ method ].call( this, val, element, rule.parameters );
|
||||
|
||||
// If a method indicates that the field is optional and therefore valid,
|
||||
// don't mark it as valid when there are no other rules
|
||||
if ( result === "dependency-mismatch" && rulesCount === 1 ) {
|
||||
dependencyMismatch = true;
|
||||
continue;
|
||||
}
|
||||
dependencyMismatch = false;
|
||||
|
||||
if ( result === "pending" ) {
|
||||
this.toHide = this.toHide.not( this.errorsFor( element ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !result ) {
|
||||
this.formatAndAdd( element, rule );
|
||||
return false;
|
||||
}
|
||||
} catch ( e ) {
|
||||
if ( this.settings.debug && window.console ) {
|
||||
console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
|
||||
}
|
||||
if ( e instanceof TypeError ) {
|
||||
e.message += ". Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.";
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
if ( dependencyMismatch ) {
|
||||
return;
|
||||
}
|
||||
if ( this.objectLength( rules ) ) {
|
||||
this.successList.push( element );
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// Return the custom message for the given element and validation method
|
||||
// specified in the element's HTML5 data attribute
|
||||
// return the generic message if present and no method specific message is present
|
||||
customDataMessage: function( element, method ) {
|
||||
return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() +
|
||||
method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" );
|
||||
},
|
||||
|
||||
// Return the custom message for the given element name and validation method
|
||||
customMessage: function( name, method ) {
|
||||
var m = this.settings.messages[ name ];
|
||||
return m && ( m.constructor === String ? m : m[ method ] );
|
||||
},
|
||||
|
||||
// Return the first defined argument, allowing empty strings
|
||||
findDefined: function() {
|
||||
for ( var i = 0; i < arguments.length; i++ ) {
|
||||
if ( arguments[ i ] !== undefined ) {
|
||||
return arguments[ i ];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
// The second parameter 'rule' used to be a string, and extended to an object literal
|
||||
// of the following form:
|
||||
// rule = {
|
||||
// method: "method name",
|
||||
// parameters: "the given method parameters"
|
||||
// }
|
||||
//
|
||||
// The old behavior still supported, kept to maintain backward compatibility with
|
||||
// old code, and will be removed in the next major release.
|
||||
defaultMessage: function( element, rule ) {
|
||||
if ( typeof rule === "string" ) {
|
||||
rule = { method: rule };
|
||||
}
|
||||
|
||||
var message = this.findDefined(
|
||||
this.customMessage( element.name, rule.method ),
|
||||
this.customDataMessage( element, rule.method ),
|
||||
|
||||
// 'title' is never undefined, so handle empty string as undefined
|
||||
!this.settings.ignoreTitle && element.title || undefined,
|
||||
$.validator.messages[ rule.method ],
|
||||
"<strong>Warning: No message defined for " + element.name + "</strong>"
|
||||
),
|
||||
theregex = /\$?\{(\d+)\}/g;
|
||||
if ( typeof message === "function" ) {
|
||||
message = message.call( this, rule.parameters, element );
|
||||
} else if ( theregex.test( message ) ) {
|
||||
message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters );
|
||||
}
|
||||
|
||||
return message;
|
||||
},
|
||||
|
||||
formatAndAdd: function( element, rule ) {
|
||||
var message = this.defaultMessage( element, rule );
|
||||
|
||||
this.errorList.push( {
|
||||
message: message,
|
||||
element: element,
|
||||
method: rule.method
|
||||
} );
|
||||
|
||||
this.errorMap[ element.name ] = message;
|
||||
this.submitted[ element.name ] = message;
|
||||
},
|
||||
|
||||
addWrapper: function( toToggle ) {
|
||||
if ( this.settings.wrapper ) {
|
||||
toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
|
||||
}
|
||||
return toToggle;
|
||||
},
|
||||
|
||||
defaultShowErrors: function() {
|
||||
var i, elements, error;
|
||||
for ( i = 0; this.errorList[ i ]; i++ ) {
|
||||
error = this.errorList[ i ];
|
||||
if ( this.settings.highlight ) {
|
||||
this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
|
||||
}
|
||||
this.showLabel( error.element, error.message );
|
||||
}
|
||||
if ( this.errorList.length ) {
|
||||
this.toShow = this.toShow.add( this.containers );
|
||||
}
|
||||
if ( this.settings.success ) {
|
||||
for ( i = 0; this.successList[ i ]; i++ ) {
|
||||
this.showLabel( this.successList[ i ] );
|
||||
}
|
||||
}
|
||||
if ( this.settings.unhighlight ) {
|
||||
for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {
|
||||
this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );
|
||||
}
|
||||
}
|
||||
this.toHide = this.toHide.not( this.toShow );
|
||||
this.hideErrors();
|
||||
this.addWrapper( this.toShow ).show();
|
||||
},
|
||||
|
||||
validElements: function() {
|
||||
return this.currentElements.not( this.invalidElements() );
|
||||
},
|
||||
|
||||
invalidElements: function() {
|
||||
return $( this.errorList ).map( function() {
|
||||
return this.element;
|
||||
} );
|
||||
},
|
||||
|
||||
showLabel: function( element, message ) {
|
||||
var place, group, errorID, v,
|
||||
error = this.errorsFor( element ),
|
||||
elementID = this.idOrName( element ),
|
||||
describedBy = $( element ).attr( "aria-describedby" );
|
||||
|
||||
if ( error.length ) {
|
||||
|
||||
// Refresh error/success class
|
||||
error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
|
||||
|
||||
// Replace message on existing label
|
||||
error.html( message );
|
||||
} else {
|
||||
|
||||
// Create error element
|
||||
error = $( "<" + this.settings.errorElement + ">" )
|
||||
.attr( "id", elementID + "-error" )
|
||||
.addClass( this.settings.errorClass )
|
||||
.html( message || "" );
|
||||
|
||||
// Maintain reference to the element to be placed into the DOM
|
||||
place = error;
|
||||
if ( this.settings.wrapper ) {
|
||||
|
||||
// Make sure the element is visible, even in IE
|
||||
// actually showing the wrapped element is handled elsewhere
|
||||
place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent();
|
||||
}
|
||||
if ( this.labelContainer.length ) {
|
||||
this.labelContainer.append( place );
|
||||
} else if ( this.settings.errorPlacement ) {
|
||||
this.settings.errorPlacement.call( this, place, $( element ) );
|
||||
} else {
|
||||
place.insertAfter( element );
|
||||
}
|
||||
|
||||
// Link error back to the element
|
||||
if ( error.is( "label" ) ) {
|
||||
|
||||
// If the error is a label, then associate using 'for'
|
||||
error.attr( "for", elementID );
|
||||
|
||||
// If the element is not a child of an associated label, then it's necessary
|
||||
// to explicitly apply aria-describedby
|
||||
} else if ( error.parents( "label[for='" + this.escapeCssMeta( elementID ) + "']" ).length === 0 ) {
|
||||
errorID = error.attr( "id" );
|
||||
|
||||
// Respect existing non-error aria-describedby
|
||||
if ( !describedBy ) {
|
||||
describedBy = errorID;
|
||||
} else if ( !describedBy.match( new RegExp( "\\b" + this.escapeCssMeta( errorID ) + "\\b" ) ) ) {
|
||||
|
||||
// Add to end of list if not already present
|
||||
describedBy += " " + errorID;
|
||||
}
|
||||
$( element ).attr( "aria-describedby", describedBy );
|
||||
|
||||
// If this element is grouped, then assign to all elements in the same group
|
||||
group = this.groups[ element.name ];
|
||||
if ( group ) {
|
||||
v = this;
|
||||
$.each( v.groups, function( name, testgroup ) {
|
||||
if ( testgroup === group ) {
|
||||
$( "[name='" + v.escapeCssMeta( name ) + "']", v.currentForm )
|
||||
.attr( "aria-describedby", error.attr( "id" ) );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !message && this.settings.success ) {
|
||||
error.text( "" );
|
||||
if ( typeof this.settings.success === "string" ) {
|
||||
error.addClass( this.settings.success );
|
||||
} else {
|
||||
this.settings.success( error, element );
|
||||
}
|
||||
}
|
||||
this.toShow = this.toShow.add( error );
|
||||
},
|
||||
|
||||
errorsFor: function( element ) {
|
||||
var name = this.escapeCssMeta( this.idOrName( element ) ),
|
||||
describer = $( element ).attr( "aria-describedby" ),
|
||||
selector = "label[for='" + name + "'], label[for='" + name + "'] *";
|
||||
|
||||
// 'aria-describedby' should directly reference the error element
|
||||
if ( describer ) {
|
||||
selector = selector + ", #" + this.escapeCssMeta( describer )
|
||||
.replace( /\s+/g, ", #" );
|
||||
}
|
||||
|
||||
return this
|
||||
.errors()
|
||||
.filter( selector );
|
||||
},
|
||||
|
||||
// See https://api.jquery.com/category/selectors/, for CSS
|
||||
// meta-characters that should be escaped in order to be used with JQuery
|
||||
// as a literal part of a name/id or any selector.
|
||||
escapeCssMeta: function( string ) {
|
||||
return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" );
|
||||
},
|
||||
|
||||
idOrName: function( element ) {
|
||||
return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );
|
||||
},
|
||||
|
||||
validationTargetFor: function( element ) {
|
||||
|
||||
// If radio/checkbox, validate first element in group instead
|
||||
if ( this.checkable( element ) ) {
|
||||
element = this.findByName( element.name );
|
||||
}
|
||||
|
||||
// Always apply ignore filter
|
||||
return $( element ).not( this.settings.ignore )[ 0 ];
|
||||
},
|
||||
|
||||
checkable: function( element ) {
|
||||
return ( /radio|checkbox/i ).test( element.type );
|
||||
},
|
||||
|
||||
findByName: function( name ) {
|
||||
return $( this.currentForm ).find( "[name='" + this.escapeCssMeta( name ) + "']" );
|
||||
},
|
||||
|
||||
getLength: function( value, element ) {
|
||||
switch ( element.nodeName.toLowerCase() ) {
|
||||
case "select":
|
||||
return $( "option:selected", element ).length;
|
||||
case "input":
|
||||
if ( this.checkable( element ) ) {
|
||||
return this.findByName( element.name ).filter( ":checked" ).length;
|
||||
}
|
||||
}
|
||||
return value.length;
|
||||
},
|
||||
|
||||
depend: function( param, element ) {
|
||||
return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true;
|
||||
},
|
||||
|
||||
dependTypes: {
|
||||
"boolean": function( param ) {
|
||||
return param;
|
||||
},
|
||||
"string": function( param, element ) {
|
||||
return !!$( param, element.form ).length;
|
||||
},
|
||||
"function": function( param, element ) {
|
||||
return param( element );
|
||||
}
|
||||
},
|
||||
|
||||
optional: function( element ) {
|
||||
var val = this.elementValue( element );
|
||||
return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch";
|
||||
},
|
||||
|
||||
startRequest: function( element ) {
|
||||
if ( !this.pending[ element.name ] ) {
|
||||
this.pendingRequest++;
|
||||
$( element ).addClass( this.settings.pendingClass );
|
||||
this.pending[ element.name ] = true;
|
||||
}
|
||||
},
|
||||
|
||||
stopRequest: function( element, valid ) {
|
||||
this.pendingRequest--;
|
||||
|
||||
// Sometimes synchronization fails, make sure pendingRequest is never < 0
|
||||
if ( this.pendingRequest < 0 ) {
|
||||
this.pendingRequest = 0;
|
||||
}
|
||||
delete this.pending[ element.name ];
|
||||
$( element ).removeClass( this.settings.pendingClass );
|
||||
if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
|
||||
$( this.currentForm ).submit();
|
||||
|
||||
// Remove the hidden input that was used as a replacement for the
|
||||
// missing submit button. The hidden input is added by `handle()`
|
||||
// to ensure that the value of the used submit button is passed on
|
||||
// for scripted submits triggered by this method
|
||||
if ( this.submitButton ) {
|
||||
$( "input:hidden[name='" + this.submitButton.name + "']", this.currentForm ).remove();
|
||||
}
|
||||
|
||||
this.formSubmitted = false;
|
||||
} else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) {
|
||||
$( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
|
||||
this.formSubmitted = false;
|
||||
}
|
||||
},
|
||||
|
||||
previousValue: function( element, method ) {
|
||||
method = typeof method === "string" && method || "remote";
|
||||
|
||||
return $.data( element, "previousValue" ) || $.data( element, "previousValue", {
|
||||
old: null,
|
||||
valid: true,
|
||||
message: this.defaultMessage( element, { method: method } )
|
||||
} );
|
||||
},
|
||||
|
||||
// Cleans up all forms and elements, removes validator-specific events
|
||||
destroy: function() {
|
||||
this.resetForm();
|
||||
|
||||
$( this.currentForm )
|
||||
.off( ".validate" )
|
||||
.removeData( "validator" )
|
||||
.find( ".validate-equalTo-blur" )
|
||||
.off( ".validate-equalTo" )
|
||||
.removeClass( "validate-equalTo-blur" );
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
classRuleSettings: {
|
||||
required: { required: true },
|
||||
email: { email: true },
|
||||
url: { url: true },
|
||||
date: { date: true },
|
||||
dateISO: { dateISO: true },
|
||||
number: { number: true },
|
||||
digits: { digits: true },
|
||||
creditcard: { creditcard: true }
|
||||
},
|
||||
|
||||
addClassRules: function( className, rules ) {
|
||||
if ( className.constructor === String ) {
|
||||
this.classRuleSettings[ className ] = rules;
|
||||
} else {
|
||||
$.extend( this.classRuleSettings, className );
|
||||
}
|
||||
},
|
||||
|
||||
classRules: function( element ) {
|
||||
var rules = {},
|
||||
classes = $( element ).attr( "class" );
|
||||
|
||||
if ( classes ) {
|
||||
$.each( classes.split( " " ), function() {
|
||||
if ( this in $.validator.classRuleSettings ) {
|
||||
$.extend( rules, $.validator.classRuleSettings[ this ] );
|
||||
}
|
||||
} );
|
||||
}
|
||||
return rules;
|
||||
},
|
||||
|
||||
normalizeAttributeRule: function( rules, type, method, value ) {
|
||||
|
||||
// Convert the value to a number for number inputs, and for text for backwards compability
|
||||
// allows type="date" and others to be compared as strings
|
||||
if ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
|
||||
value = Number( value );
|
||||
|
||||
// Support Opera Mini, which returns NaN for undefined minlength
|
||||
if ( isNaN( value ) ) {
|
||||
value = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if ( value || value === 0 ) {
|
||||
rules[ method ] = value;
|
||||
} else if ( type === method && type !== "range" ) {
|
||||
|
||||
// Exception: the jquery validate 'range' method
|
||||
// does not test for the html5 'range' type
|
||||
rules[ method ] = true;
|
||||
}
|
||||
},
|
||||
|
||||
attributeRules: function( element ) {
|
||||
var rules = {},
|
||||
$element = $( element ),
|
||||
type = element.getAttribute( "type" ),
|
||||
method, value;
|
||||
|
||||
for ( method in $.validator.methods ) {
|
||||
|
||||
// Support for <input required> in both html5 and older browsers
|
||||
if ( method === "required" ) {
|
||||
value = element.getAttribute( method );
|
||||
|
||||
// Some browsers return an empty string for the required attribute
|
||||
// and non-HTML5 browsers might have required="" markup
|
||||
if ( value === "" ) {
|
||||
value = true;
|
||||
}
|
||||
|
||||
// Force non-HTML5 browsers to return bool
|
||||
value = !!value;
|
||||
} else {
|
||||
value = $element.attr( method );
|
||||
}
|
||||
|
||||
this.normalizeAttributeRule( rules, type, method, value );
|
||||
}
|
||||
|
||||
// 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs
|
||||
if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {
|
||||
delete rules.maxlength;
|
||||
}
|
||||
|
||||
return rules;
|
||||
},
|
||||
|
||||
dataRules: function( element ) {
|
||||
var rules = {},
|
||||
$element = $( element ),
|
||||
type = element.getAttribute( "type" ),
|
||||
method, value;
|
||||
|
||||
for ( method in $.validator.methods ) {
|
||||
value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
|
||||
this.normalizeAttributeRule( rules, type, method, value );
|
||||
}
|
||||
return rules;
|
||||
},
|
||||
|
||||
staticRules: function( element ) {
|
||||
var rules = {},
|
||||
validator = $.data( element.form, "validator" );
|
||||
|
||||
if ( validator.settings.rules ) {
|
||||
rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};
|
||||
}
|
||||
return rules;
|
||||
},
|
||||
|
||||
normalizeRules: function( rules, element ) {
|
||||
|
||||
// Handle dependency check
|
||||
$.each( rules, function( prop, val ) {
|
||||
|
||||
// Ignore rule when param is explicitly false, eg. required:false
|
||||
if ( val === false ) {
|
||||
delete rules[ prop ];
|
||||
return;
|
||||
}
|
||||
if ( val.param || val.depends ) {
|
||||
var keepRule = true;
|
||||
switch ( typeof val.depends ) {
|
||||
case "string":
|
||||
keepRule = !!$( val.depends, element.form ).length;
|
||||
break;
|
||||
case "function":
|
||||
keepRule = val.depends.call( element, element );
|
||||
break;
|
||||
}
|
||||
if ( keepRule ) {
|
||||
rules[ prop ] = val.param !== undefined ? val.param : true;
|
||||
} else {
|
||||
$.data( element.form, "validator" ).resetElements( $( element ) );
|
||||
delete rules[ prop ];
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// Evaluate parameters
|
||||
$.each( rules, function( rule, parameter ) {
|
||||
rules[ rule ] = $.isFunction( parameter ) && rule !== "normalizer" ? parameter( element ) : parameter;
|
||||
} );
|
||||
|
||||
// Clean number parameters
|
||||
$.each( [ "minlength", "maxlength" ], function() {
|
||||
if ( rules[ this ] ) {
|
||||
rules[ this ] = Number( rules[ this ] );
|
||||
}
|
||||
} );
|
||||
$.each( [ "rangelength", "range" ], function() {
|
||||
var parts;
|
||||
if ( rules[ this ] ) {
|
||||
if ( $.isArray( rules[ this ] ) ) {
|
||||
rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ];
|
||||
} else if ( typeof rules[ this ] === "string" ) {
|
||||
parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ );
|
||||
rules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ];
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
if ( $.validator.autoCreateRanges ) {
|
||||
|
||||
// Auto-create ranges
|
||||
if ( rules.min != null && rules.max != null ) {
|
||||
rules.range = [ rules.min, rules.max ];
|
||||
delete rules.min;
|
||||
delete rules.max;
|
||||
}
|
||||
if ( rules.minlength != null && rules.maxlength != null ) {
|
||||
rules.rangelength = [ rules.minlength, rules.maxlength ];
|
||||
delete rules.minlength;
|
||||
delete rules.maxlength;
|
||||
}
|
||||
}
|
||||
|
||||
return rules;
|
||||
},
|
||||
|
||||
// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
|
||||
normalizeRule: function( data ) {
|
||||
if ( typeof data === "string" ) {
|
||||
var transformed = {};
|
||||
$.each( data.split( /\s/ ), function() {
|
||||
transformed[ this ] = true;
|
||||
} );
|
||||
data = transformed;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/jQuery.validator.addMethod/
|
||||
addMethod: function( name, method, message ) {
|
||||
$.validator.methods[ name ] = method;
|
||||
$.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];
|
||||
if ( method.length < 3 ) {
|
||||
$.validator.addClassRules( name, $.validator.normalizeRule( name ) );
|
||||
}
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/jQuery.validator.methods/
|
||||
methods: {
|
||||
|
||||
// https://jqueryvalidation.org/required-method/
|
||||
required: function( value, element, param ) {
|
||||
|
||||
// Check if dependency is met
|
||||
if ( !this.depend( param, element ) ) {
|
||||
return "dependency-mismatch";
|
||||
}
|
||||
if ( element.nodeName.toLowerCase() === "select" ) {
|
||||
|
||||
// Could be an array for select-multiple or a string, both are fine this way
|
||||
var val = $( element ).val();
|
||||
return val && val.length > 0;
|
||||
}
|
||||
if ( this.checkable( element ) ) {
|
||||
return this.getLength( value, element ) > 0;
|
||||
}
|
||||
return value.length > 0;
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/email-method/
|
||||
email: function( value, element ) {
|
||||
|
||||
// From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
|
||||
// Retrieved 2014-01-14
|
||||
// If you have a problem with this implementation, report a bug against the above spec
|
||||
// Or use custom methods to implement your own email validation
|
||||
return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/url-method/
|
||||
url: function( value, element ) {
|
||||
|
||||
// Copyright (c) 2010-2013 Diego Perini, MIT licensed
|
||||
// https://gist.github.com/dperini/729294
|
||||
// see also https://mathiasbynens.be/demo/url-regex
|
||||
// modified to allow protocol-relative URLs
|
||||
return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/date-method/
|
||||
date: function( value, element ) {
|
||||
return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/dateISO-method/
|
||||
dateISO: function( value, element ) {
|
||||
return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/number-method/
|
||||
number: function( value, element ) {
|
||||
return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/digits-method/
|
||||
digits: function( value, element ) {
|
||||
return this.optional( element ) || /^\d+$/.test( value );
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/minlength-method/
|
||||
minlength: function( value, element, param ) {
|
||||
var length = $.isArray( value ) ? value.length : this.getLength( value, element );
|
||||
return this.optional( element ) || length >= param;
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/maxlength-method/
|
||||
maxlength: function( value, element, param ) {
|
||||
var length = $.isArray( value ) ? value.length : this.getLength( value, element );
|
||||
return this.optional( element ) || length <= param;
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/rangelength-method/
|
||||
rangelength: function( value, element, param ) {
|
||||
var length = $.isArray( value ) ? value.length : this.getLength( value, element );
|
||||
return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/min-method/
|
||||
min: function( value, element, param ) {
|
||||
return this.optional( element ) || value >= param;
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/max-method/
|
||||
max: function( value, element, param ) {
|
||||
return this.optional( element ) || value <= param;
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/range-method/
|
||||
range: function( value, element, param ) {
|
||||
return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/step-method/
|
||||
step: function( value, element, param ) {
|
||||
var type = $( element ).attr( "type" ),
|
||||
errorMessage = "Step attribute on input type " + type + " is not supported.",
|
||||
supportedTypes = [ "text", "number", "range" ],
|
||||
re = new RegExp( "\\b" + type + "\\b" ),
|
||||
notSupported = type && !re.test( supportedTypes.join() ),
|
||||
decimalPlaces = function( num ) {
|
||||
var match = ( "" + num ).match( /(?:\.(\d+))?$/ );
|
||||
if ( !match ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Number of digits right of decimal point.
|
||||
return match[ 1 ] ? match[ 1 ].length : 0;
|
||||
},
|
||||
toInt = function( num ) {
|
||||
return Math.round( num * Math.pow( 10, decimals ) );
|
||||
},
|
||||
valid = true,
|
||||
decimals;
|
||||
|
||||
// Works only for text, number and range input types
|
||||
// TODO find a way to support input types date, datetime, datetime-local, month, time and week
|
||||
if ( notSupported ) {
|
||||
throw new Error( errorMessage );
|
||||
}
|
||||
|
||||
decimals = decimalPlaces( param );
|
||||
|
||||
// Value can't have too many decimals
|
||||
if ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return this.optional( element ) || valid;
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/equalTo-method/
|
||||
equalTo: function( value, element, param ) {
|
||||
|
||||
// Bind to the blur event of the target in order to revalidate whenever the target field is updated
|
||||
var target = $( param );
|
||||
if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) {
|
||||
target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() {
|
||||
$( element ).valid();
|
||||
} );
|
||||
}
|
||||
return value === target.val();
|
||||
},
|
||||
|
||||
// https://jqueryvalidation.org/remote-method/
|
||||
remote: function( value, element, param, method ) {
|
||||
if ( this.optional( element ) ) {
|
||||
return "dependency-mismatch";
|
||||
}
|
||||
|
||||
method = typeof method === "string" && method || "remote";
|
||||
|
||||
var previous = this.previousValue( element, method ),
|
||||
validator, data, optionDataString;
|
||||
|
||||
if ( !this.settings.messages[ element.name ] ) {
|
||||
this.settings.messages[ element.name ] = {};
|
||||
}
|
||||
previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ];
|
||||
this.settings.messages[ element.name ][ method ] = previous.message;
|
||||
|
||||
param = typeof param === "string" && { url: param } || param;
|
||||
optionDataString = $.param( $.extend( { data: value }, param.data ) );
|
||||
if ( previous.old === optionDataString ) {
|
||||
return previous.valid;
|
||||
}
|
||||
|
||||
previous.old = optionDataString;
|
||||
validator = this;
|
||||
this.startRequest( element );
|
||||
data = {};
|
||||
data[ element.name ] = value;
|
||||
$.ajax( $.extend( true, {
|
||||
mode: "abort",
|
||||
port: "validate" + element.name,
|
||||
dataType: "json",
|
||||
data: data,
|
||||
context: validator.currentForm,
|
||||
success: function( response ) {
|
||||
var valid = response === true || response === "true",
|
||||
errors, message, submitted;
|
||||
|
||||
validator.settings.messages[ element.name ][ method ] = previous.originalMessage;
|
||||
if ( valid ) {
|
||||
submitted = validator.formSubmitted;
|
||||
validator.resetInternals();
|
||||
validator.toHide = validator.errorsFor( element );
|
||||
validator.formSubmitted = submitted;
|
||||
validator.successList.push( element );
|
||||
validator.invalid[ element.name ] = false;
|
||||
validator.showErrors();
|
||||
} else {
|
||||
errors = {};
|
||||
message = response || validator.defaultMessage( element, { method: method, parameters: value } );
|
||||
errors[ element.name ] = previous.message = message;
|
||||
validator.invalid[ element.name ] = true;
|
||||
validator.showErrors( errors );
|
||||
}
|
||||
previous.valid = valid;
|
||||
validator.stopRequest( element, valid );
|
||||
}
|
||||
}, param ) );
|
||||
return "pending";
|
||||
}
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
// Ajax mode: abort
|
||||
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
|
||||
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
|
||||
|
||||
var pendingRequests = {},
|
||||
ajax;
|
||||
|
||||
// Use a prefilter if available (1.5+)
|
||||
if ( $.ajaxPrefilter ) {
|
||||
$.ajaxPrefilter( function( settings, _, xhr ) {
|
||||
var port = settings.port;
|
||||
if ( settings.mode === "abort" ) {
|
||||
if ( pendingRequests[ port ] ) {
|
||||
pendingRequests[ port ].abort();
|
||||
}
|
||||
pendingRequests[ port ] = xhr;
|
||||
}
|
||||
} );
|
||||
} else {
|
||||
|
||||
// Proxy ajax
|
||||
ajax = $.ajax;
|
||||
$.ajax = function( settings ) {
|
||||
var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
|
||||
port = ( "port" in settings ? settings : $.ajaxSettings ).port;
|
||||
if ( mode === "abort" ) {
|
||||
if ( pendingRequests[ port ] ) {
|
||||
pendingRequests[ port ].abort();
|
||||
}
|
||||
pendingRequests[ port ] = ajax.apply( this, arguments );
|
||||
return pendingRequests[ port ];
|
||||
}
|
||||
return ajax.apply( this, arguments );
|
||||
};
|
||||
}
|
||||
return $;
|
||||
}));
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "jquery",
|
||||
"main": "dist/jquery.js",
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"package.json"
|
||||
],
|
||||
"keywords": [
|
||||
"jquery",
|
||||
"javascript",
|
||||
"browser",
|
||||
"library"
|
||||
],
|
||||
"homepage": "https://github.com/jquery/jquery-dist",
|
||||
"version": "3.3.1",
|
||||
"_release": "3.3.1",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "3.3.1",
|
||||
"commit": "9e8ec3d10fad04748176144f108d7355662ae75e"
|
||||
},
|
||||
"_source": "https://github.com/jquery/jquery-dist.git",
|
||||
"_target": "^3.3.1",
|
||||
"_originalSource": "jquery",
|
||||
"_direct": true
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals. For exact contribution history, see the revision history
|
||||
available at https://github.com/jquery/jquery
|
||||
|
||||
The following license applies to all parts of this software except as
|
||||
documented below:
|
||||
|
||||
====
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
====
|
||||
|
||||
All files located in the node_modules and external directories are
|
||||
externally maintained libraries used by this software which have their
|
||||
own licenses; we recommend you read them, as their terms may differ from
|
||||
the terms above.
|