2018-01-09 20:18:49 -08:00
! function ( t ) { function e ( i ) { if ( n [ i ] ) return n [ i ] . exports ; var r = n [ i ] = { i : i , l : ! 1 , exports : { } } ; return t [ i ] . call ( r . exports , r , r . exports , e ) , r . l = ! 0 , r . exports } var n = { } ; e . m = t , e . c = n , e . d = function ( t , n , i ) { e . o ( t , n ) || Object . defineProperty ( t , n , { configurable : ! 1 , enumerable : ! 0 , get : i } ) } , e . n = function ( t ) { var n = t && t . _ _esModule ? function ( ) { return t . default } : function ( ) { return t } ; return e . d ( n , "a" , n ) , n } , e . o = function ( t , e ) { return Object . prototype . hasOwnProperty . call ( t , e ) } , e . p = "" , e ( e . s = 0 ) } ( { "+B67" : function ( t , e , n ) { var i = n ( "/Psq" ) ; "string" == typeof i && ( i = [ [ t . i , i , "" ] ] ) , i . locals && ( t . exports = i . locals ) ; n ( "rjj0" ) ( "6e100439" , i , ! 0 ) } , "/Psq" : function ( t , e , n ) { e = t . exports = n ( "FZ+f" ) ( void 0 ) , e . push ( [ t . i , "" , "" ] ) } , 0 : function ( t , e , n ) { n ( "GDnL" ) , n ( "Bqz+" ) , n ( "1CH1" ) , t . exports = n ( "f5J3" ) } , 1 : function ( t , e ) { } , "1CH1" : function ( t , e ) { } , "3IRH" : function ( t , e ) { t . exports = function ( t ) { return t . webpackPolyfill || ( t . deprecate = function ( ) { } , t . paths = [ ] , t . children || ( t . children = [ ] ) , Object . defineProperty ( t , "loaded" , { enumerable : ! 0 , get : function ( ) { return t . l } } ) , Object . defineProperty ( t , "id" , { enumerable : ! 0 , get : function ( ) { return t . i } } ) , t . webpackPolyfill = 1 ) , t } } , "4dDV" : function ( t , e , n ) { var i = n ( "aLss" ) ; "string" == typeof i && ( i = [ [ t . i , i , "" ] ] ) , i . locals && ( t . exports = i . locals ) ; n ( "rjj0" ) ( "aa37c4a4" , i , ! 0 ) } , "6dED" : function ( t , e ) { t . exports = { render : function ( ) { var t = this , e = t . $createElement , n = t . _self . _c || e ; return n ( "div" , [ n ( "div" , [ n ( "div" , { staticClass : "panel panel-default" } , [ n ( "div" , { staticClass : "panel-heading" } , [ n ( "div" , { staticStyle : { display : "flex" , "justify-content" : "space-between" , "align-items" : "center" } } , [ n ( "span" , [ t . _v ( "\n Personal Access Tokens\n " ) ] ) , t . _v ( " " ) , n ( "a" , { staticClass : "action-link" , on : { click : t . showCreateTokenForm } } , [ t . _v ( "\n Create New Token\n " ) ] ) ] ) ] ) , t . _v ( " " ) , n ( "div" , { staticClass : "panel-body" } , [ 0 === t . tokens . length ? n ( "p" , { staticClass : "m-b-none" } , [ t . _v ( "\n You have not created any personal access tokens.\n " ) ] ) : t . _e ( ) , t . _v ( " " ) , t . tokens . length > 0 ? n ( "table" , { staticClass : "table table-borderless m-b-none" } , [ t . _m ( 0 ) , t . _v ( " " ) , n ( "tbody" , t . _l ( t . tokens , function ( e ) { return n ( "tr" , [ n ( "td" , { staticStyle : { "vertical-align" : "middle" } } , [ t . _v ( "\n " + t . _s ( e . name ) + "\n " ) ] ) , t . _v ( " " ) , n ( "td" , { staticStyle : { "vertical-align" : "middle" } } , [ n ( "a" , { staticClass : "action-link text-danger" , on : { click : function ( n ) { t . revoke ( e ) } } } , [ t . _v ( "\n Delete\n " ) ] ) ] ) ] ) } ) ) ] ) : t . _e ( ) ] ) ] ) ] ) , t . _v ( " " ) , n ( "div" , { staticClass : "modal fade" , attrs : { id : "modal-create-token" , tabindex : "-1" , role : "dialog" } } , [ n ( "div" , { staticClass : "modal-dialog" } , [ n ( "div" , { staticClass : "modal-content" } , [ t . _m ( 1 ) , t . _v ( " " ) , n ( "div" , { staticClass : "modal-body" } , [ t . form . errors . length > 0 ? n ( "div" , { staticClass : "alert alert-danger" } , [ t . _m ( 2 ) , t . _v ( " " ) , n ( "br" ) , t . _v ( " " ) , n ( "ul" , t . _l ( t . form . errors , function ( e ) { return n ( "li" , [ t . _v ( "\n " + t . _s ( e ) + "\n " ) ] ) } ) ) ] ) : t . _e ( ) , t . _v ( " " ) , n ( "form" , { staticClass : "form-horizontal" , attrs : { role : "form" } , on : { submit : function ( e ) { e . preventDefault ( ) , t . store ( e ) } } } , [ n ( "div" , { staticClass : "form-group" } , [ n ( "label" , { staticClass : "col-md-4 control-label" } , [ t . _v ( "Name" ) ] ) , t . _v ( " " ) , n ( "div" , { staticClass : "col-md-6" } , [ n ( "input" , { directives : [ { name : "model" , rawName : "v-model" , value : t . form . name , expression : "form.name" } ] , staticClass : "form-control" , attrs : { id : "create-token-name" , type : "text" , name : "name" } , domProps : { value : t . form . name } , on : { input : function ( e ) { e . target . composing || ( t . form . name = e . target . value ) } } } ) ] ) ] ) , t . _v ( " " ) , t . scopes . length > 0 ? n ( "div" , { staticClass : "form-group" } , [ n ( "label" , { staticClass : "col-md-4 control-label" } , [ t . _v ( "Scopes" ) ] ) , t . _v ( " " ) , n ( "div" , { staticClass : "col-md-6" } , t . _l ( t . scopes , function ( e ) { return n ( "div" , [ n ( "div" , { staticClass : "checkbox" } , [ n ( "label" , [ n ( "input" , { attrs : { type : "checkbox" } , domProps : { checked : t . scopeIsAssigned ( e . id ) } , on : { click : function ( n ) { t . toggleScope ( e . id ) } } } ) , t . _v ( "\n\n " + t . _s ( e . id ) + "\n " ) ] ) ] ) ] ) } ) ) ] ) : t .
//# sourceMappingURL=vue.js.map
! function ( t , e ) { "function" == typeof define && define . amd ? define ( e ) : "object" == typeof exports ? module . exports = e ( require , exports , module ) : t . Tether = e ( ) } ( this , function ( t , e , o ) { "use strict" ; function i ( t , e ) { if ( ! ( t instanceof e ) ) throw new TypeError ( "Cannot call a class as a function" ) } function n ( t ) { var e = t . getBoundingClientRect ( ) , o = { } ; for ( var i in e ) o [ i ] = e [ i ] ; if ( t . ownerDocument !== document ) { var r = t . ownerDocument . defaultView . frameElement ; if ( r ) { var s = n ( r ) ; o . top += s . top , o . bottom += s . top , o . left += s . left , o . right += s . left } } return o } function r ( t ) { var e = getComputedStyle ( t ) || { } , o = e . position , i = [ ] ; if ( "fixed" === o ) return [ t ] ; for ( var n = t ; ( n = n . parentNode ) && n && 1 === n . nodeType ; ) { var r = void 0 ; try { r = getComputedStyle ( n ) } catch ( s ) { } if ( "undefined" == typeof r || null === r ) return i . push ( n ) , i ; var a = r , f = a . overflow , l = a . overflowX , h = a . overflowY ; /(auto|scroll)/ . test ( f + h + l ) && ( "absolute" !== o || [ "relative" , "absolute" , "fixed" ] . indexOf ( r . position ) >= 0 ) && i . push ( n ) } return i . push ( t . ownerDocument . body ) , t . ownerDocument !== document && i . push ( t . ownerDocument . defaultView ) , i } function s ( ) { A && document . body . removeChild ( A ) , A = null } function a ( t ) { var e = void 0 ; t === document ? ( e = document , t = document . documentElement ) : e = t . ownerDocument ; var o = e . documentElement , i = n ( t ) , r = P ( ) ; return i . top -= r . top , i . left -= r . left , "undefined" == typeof i . width && ( i . width = document . body . scrollWidth - i . left - i . right ) , "undefined" == typeof i . height && ( i . height = document . body . scrollHeight - i . top - i . bottom ) , i . top = i . top - o . clientTop , i . left = i . left - o . clientLeft , i . right = e . body . clientWidth - i . width - i . left , i . bottom = e . body . clientHeight - i . height - i . top , i } function f ( t ) { return t . offsetParent || document . documentElement } function l ( ) { if ( M ) return M ; var t = document . createElement ( "div" ) ; t . style . width = "100%" , t . style . height = "200px" ; var e = document . createElement ( "div" ) ; h ( e . style , { position : "absolute" , top : 0 , left : 0 , pointerEvents : "none" , visibility : "hidden" , width : "200px" , height : "150px" , overflow : "hidden" } ) , e . appendChild ( t ) , document . body . appendChild ( e ) ; var o = t . offsetWidth ; e . style . overflow = "scroll" ; var i = t . offsetWidth ; o === i && ( i = e . clientWidth ) , document . body . removeChild ( e ) ; var n = o - i ; return M = { width : n , height : n } } function h ( ) { var t = arguments . length <= 0 || void 0 === arguments [ 0 ] ? { } : arguments [ 0 ] , e = [ ] ; return Array . prototype . push . apply ( e , arguments ) , e . slice ( 1 ) . forEach ( function ( e ) { if ( e ) for ( var o in e ) ( { } ) . hasOwnProperty . call ( e , o ) && ( t [ o ] = e [ o ] ) } ) , t } function d ( t , e ) { if ( "undefined" != typeof t . classList ) e . split ( " " ) . forEach ( function ( e ) { e . trim ( ) && t . classList . remove ( e ) } ) ; else { var o = new RegExp ( "(^| )" + e . split ( " " ) . join ( "|" ) + "( |$)" , "gi" ) , i = c ( t ) . replace ( o , " " ) ; g ( t , i ) } } function p ( t , e ) { if ( "undefined" != typeof t . classList ) e . split ( " " ) . forEach ( function ( e ) { e . trim ( ) && t . classList . add ( e ) } ) ; else { d ( t , e ) ; var o = c ( t ) + ( " " + e ) ; g ( t , o ) } } function u ( t , e ) { if ( "undefined" != typeof t . classList ) return t . classList . contains ( e ) ; var o = c ( t ) ; return new RegExp ( "(^| )" + e + "( |$)" , "gi" ) . test ( o ) } function c ( t ) { return t . className instanceof t . ownerDocument . defaultView . SVGAnimatedString ? t . className . baseVal : t . className } function g ( t , e ) { t . setAttribute ( "class" , e ) } function m ( t , e , o ) { o . forEach ( function ( o ) { e . indexOf ( o ) === - 1 && u ( t , o ) && d ( t , o ) } ) , e . forEach ( function ( e ) { u ( t , e ) || p ( t , e ) } ) } function i ( t , e ) { if ( ! ( t instanceof e ) ) throw new TypeError ( "Cannot call a class as a function" ) } function v ( t , e ) { if ( "function" != typeof e && null !== e ) throw new TypeError ( "Super expression must either be null or a function, not " + typeof e ) ; t . prototype = Object . create ( e && e . prototype , { constructor : { value : t , enumerable : ! 1 , writable : ! 0 , configurable : ! 0 } } ) , e && ( Object . setPrototypeOf ? Object . setPrototypeOf ( t , e ) : t . _ _proto _ _ = e ) } function y ( t , e ) { var o = arguments . length <= 2 || void 0 === arguments [ 2 ] ? 1 : arguments [ 2 ] ; return t + o >= e && e >= t - o } function b ( ) { return "undefined" != typeof performance && "undefined" != typeof performance . now ? performance . now ( ) : + new Date } function w ( ) { for ( var t = { top : 0 , left : 0 } , e = arguments . length , o = Array ( e ) , i = 0 ; i < e ; i ++ ) o [ i ] = arguments [ i ] ; return o . forEach ( function ( e ) { var o = e . top , i = e . left ; "string" == typeof o && ( o = parseFloat ( o , 10 ) ) , "string" == typeof i && ( i = parseFloat ( i , 10 ) ) , t . top += o , t . left += i } ) , t } function C ( t , e ) { return "string" == typeof t . left && t . left . indexOf ( "%" ) !== - 1 && ( t . left = parseFloat ( t . left , 10 ) / 100 * e . widt
2017-12-28 20:08:45 -08:00
/*! Copyright (c) 2011 Piotr Rochala (http:/ / rocha . la )
* Dual licensed under the MIT ( http : //www.opensource.org/licenses/mit-license.php)
* and GPL ( http : //www.opensource.org/licenses/gpl-license.php) licenses.
*
* Version : 1.3 . 8
*
* /
( function ( $ ) {
$ . fn . extend ( {
slimScroll : function ( options ) {
var defaults = {
// width in pixels of the visible scroll area
width : 'auto' ,
// height in pixels of the visible scroll area
height : '250px' ,
// width in pixels of the scrollbar and rail
size : '7px' ,
// scrollbar color, accepts any hex/color value
color : '#000' ,
// scrollbar position - left/right
position : 'right' ,
// distance in pixels between the side edge and the scrollbar
distance : '1px' ,
// default scroll position on load - top / bottom / $('selector')
start : 'top' ,
// sets scrollbar opacity
opacity : . 4 ,
// enables always-on mode for the scrollbar
alwaysVisible : false ,
// check if we should hide the scrollbar when user is hovering over
disableFadeOut : false ,
// sets visibility of the rail
railVisible : false ,
// sets rail color
railColor : '#333' ,
// sets rail opacity
railOpacity : . 2 ,
// whether we should use jQuery UI Draggable to enable bar dragging
railDraggable : true ,
// defautlt CSS class of the slimscroll rail
railClass : 'slimScrollRail' ,
// defautlt CSS class of the slimscroll bar
barClass : 'slimScrollBar' ,
// defautlt CSS class of the slimscroll wrapper
wrapperClass : 'slimScrollDiv' ,
// check if mousewheel should scroll the window if we reach top/bottom
allowPageScroll : false ,
// scroll amount applied to each mouse wheel step
wheelStep : 20 ,
// scroll amount applied when user is using gestures
touchScrollStep : 200 ,
// sets border radius
borderRadius : '7px' ,
// sets border radius of the rail
railBorderRadius : '7px'
} ;
var o = $ . extend ( defaults , options ) ;
// do it for every element that matches selector
this . each ( function ( ) {
var isOverPanel , isOverBar , isDragg , queueHide , touchDif ,
barHeight , percentScroll , lastScroll ,
divS = '<div></div>' ,
minBarHeight = 30 ,
releaseScroll = false ;
// used in event handlers and for better minification
var me = $ ( this ) ;
// ensure we are not binding it again
if ( me . parent ( ) . hasClass ( o . wrapperClass ) )
{
// start from last bar position
var offset = me . scrollTop ( ) ;
// find bar and rail
bar = me . siblings ( '.' + o . barClass ) ;
rail = me . siblings ( '.' + o . railClass ) ;
getBarHeight ( ) ;
// check if we should scroll existing instance
if ( $ . isPlainObject ( options ) )
{
// Pass height: auto to an existing slimscroll object to force a resize after contents have changed
if ( 'height' in options && options . height == 'auto' ) {
me . parent ( ) . css ( 'height' , 'auto' ) ;
me . css ( 'height' , 'auto' ) ;
var height = me . parent ( ) . parent ( ) . height ( ) ;
me . parent ( ) . css ( 'height' , height ) ;
me . css ( 'height' , height ) ;
} else if ( 'height' in options ) {
var h = options . height ;
me . parent ( ) . css ( 'height' , h ) ;
me . css ( 'height' , h ) ;
}
if ( 'scrollTo' in options )
{
// jump to a static point
offset = parseInt ( o . scrollTo ) ;
}
else if ( 'scrollBy' in options )
{
// jump by value pixels
offset += parseInt ( o . scrollBy ) ;
}
else if ( 'destroy' in options )
{
// remove slimscroll elements
bar . remove ( ) ;
rail . remove ( ) ;
me . unwrap ( ) ;
return ;
}
// scroll content by the given offset
scrollContent ( offset , false , true ) ;
}
return ;
}
else if ( $ . isPlainObject ( options ) )
{
if ( 'destroy' in options )
{
return ;
}
}
// optionally set height to the parent's height
o . height = ( o . height == 'auto' ) ? me . parent ( ) . height ( ) : o . height ;
// wrap content
var wrapper = $ ( divS )
. addClass ( o . wrapperClass )
. css ( {
position : 'relative' ,
overflow : 'hidden' ,
width : o . width ,
height : o . height
} ) ;
// update style for the div
me . css ( {
overflow : 'hidden' ,
width : o . width ,
height : o . height
} ) ;
// create scrollbar rail
var rail = $ ( divS )
. addClass ( o . railClass )
. css ( {
width : o . size ,
height : '100%' ,
position : 'absolute' ,
top : 0 ,
display : ( o . alwaysVisible && o . railVisible ) ? 'block' : 'none' ,
'border-radius' : o . railBorderRadius ,
background : o . railColor ,
opacity : o . railOpacity ,
zIndex : 90
} ) ;
// create scrollbar
var bar = $ ( divS )
. addClass ( o . barClass )
. css ( {
background : o . color ,
width : o . size ,
position : 'absolute' ,
top : 0 ,
opacity : o . opacity ,
display : o . alwaysVisible ? 'block' : 'none' ,
'border-radius' : o . borderRadius ,
BorderRadius : o . borderRadius ,
MozBorderRadius : o . borderRadius ,
WebkitBorderRadius : o . borderRadius ,
zIndex : 99
} ) ;
// set position
var posCss = ( o . position == 'right' ) ? { right : o . distance } : { left : o . distance } ;
rail . css ( posCss ) ;
bar . css ( posCss ) ;
// wrap it
me . wrap ( wrapper ) ;
// append to parent div
me . parent ( ) . append ( bar ) ;
me . parent ( ) . append ( rail ) ;
// make it draggable and no longer dependent on the jqueryUI
if ( o . railDraggable ) {
bar . bind ( "mousedown" , function ( e ) {
var $doc = $ ( document ) ;
isDragg = true ;
t = parseFloat ( bar . css ( 'top' ) ) ;
pageY = e . pageY ;
$doc . bind ( "mousemove.slimscroll" , function ( e ) {
currTop = t + e . pageY - pageY ;
bar . css ( 'top' , currTop ) ;
scrollContent ( 0 , bar . position ( ) . top , false ) ; // scroll content
} ) ;
$doc . bind ( "mouseup.slimscroll" , function ( e ) {
isDragg = false ; hideBar ( ) ;
$doc . unbind ( '.slimscroll' ) ;
} ) ;
return false ;
} ) . bind ( "selectstart.slimscroll" , function ( e ) {
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
return false ;
} ) ;
}
// on rail over
rail . hover ( function ( ) {
showBar ( ) ;
} , function ( ) {
hideBar ( ) ;
} ) ;
// on bar over
bar . hover ( function ( ) {
isOverBar = true ;
} , function ( ) {
isOverBar = false ;
} ) ;
// show on parent mouseover
me . hover ( function ( ) {
isOverPanel = true ;
showBar ( ) ;
hideBar ( ) ;
} , function ( ) {
isOverPanel = false ;
hideBar ( ) ;
} ) ;
// support for mobile
me . bind ( 'touchstart' , function ( e , b ) {
if ( e . originalEvent . touches . length )
{
// record where touch started
touchDif = e . originalEvent . touches [ 0 ] . pageY ;
}
} ) ;
me . bind ( 'touchmove' , function ( e ) {
// prevent scrolling the page if necessary
if ( ! releaseScroll )
{
e . originalEvent . preventDefault ( ) ;
}
if ( e . originalEvent . touches . length )
{
// see how far user swiped
var diff = ( touchDif - e . originalEvent . touches [ 0 ] . pageY ) / o . touchScrollStep ;
// scroll content
scrollContent ( diff , true ) ;
touchDif = e . originalEvent . touches [ 0 ] . pageY ;
}
} ) ;
// set up initial height
getBarHeight ( ) ;
// check start position
if ( o . start === 'bottom' )
{
// scroll content to bottom
bar . css ( { top : me . outerHeight ( ) - bar . outerHeight ( ) } ) ;
scrollContent ( 0 , true ) ;
}
else if ( o . start !== 'top' )
{
// assume jQuery selector
scrollContent ( $ ( o . start ) . position ( ) . top , null , true ) ;
// make sure bar stays hidden
if ( ! o . alwaysVisible ) { bar . hide ( ) ; }
}
// attach scroll events
attachWheel ( this ) ;
function _onWheel ( e )
{
// use mouse wheel only when mouse is over
if ( ! isOverPanel ) { return ; }
var e = e || window . event ;
var delta = 0 ;
if ( e . wheelDelta ) { delta = - e . wheelDelta / 120 ; }
if ( e . detail ) { delta = e . detail / 3 ; }
var target = e . target || e . srcTarget || e . srcElement ;
if ( $ ( target ) . closest ( '.' + o . wrapperClass ) . is ( me . parent ( ) ) ) {
// scroll content
scrollContent ( delta , true ) ;
}
// stop window scroll
if ( e . preventDefault && ! releaseScroll ) { e . preventDefault ( ) ; }
if ( ! releaseScroll ) { e . returnValue = false ; }
}
function scrollContent ( y , isWheel , isJump )
{
releaseScroll = false ;
var delta = y ;
var maxTop = me . outerHeight ( ) - bar . outerHeight ( ) ;
if ( isWheel )
{
// move bar with mouse wheel
delta = parseInt ( bar . css ( 'top' ) ) + y * parseInt ( o . wheelStep ) / 100 * bar . outerHeight ( ) ;
// move bar, make sure it doesn't go out
delta = Math . min ( Math . max ( delta , 0 ) , maxTop ) ;
// if scrolling down, make sure a fractional change to the
// scroll position isn't rounded away when the scrollbar's CSS is set
// this flooring of delta would happened automatically when
// bar.css is set below, but we floor here for clarity
delta = ( y > 0 ) ? Math . ceil ( delta ) : Math . floor ( delta ) ;
// scroll the scrollbar
bar . css ( { top : delta + 'px' } ) ;
}
// calculate actual scroll amount
percentScroll = parseInt ( bar . css ( 'top' ) ) / ( me . outerHeight ( ) - bar . outerHeight ( ) ) ;
delta = percentScroll * ( me [ 0 ] . scrollHeight - me . outerHeight ( ) ) ;
if ( isJump )
{
delta = y ;
var offsetTop = delta / me [ 0 ] . scrollHeight * me . outerHeight ( ) ;
offsetTop = Math . min ( Math . max ( offsetTop , 0 ) , maxTop ) ;
bar . css ( { top : offsetTop + 'px' } ) ;
}
// scroll content
me . scrollTop ( delta ) ;
// fire scrolling event
me . trigger ( 'slimscrolling' , ~ ~ delta ) ;
// ensure bar is visible
showBar ( ) ;
// trigger hide when scroll is stopped
hideBar ( ) ;
}
function attachWheel ( target )
{
if ( window . addEventListener )
{
target . addEventListener ( 'DOMMouseScroll' , _onWheel , false ) ;
target . addEventListener ( 'mousewheel' , _onWheel , false ) ;
}
else
{
document . attachEvent ( "onmousewheel" , _onWheel )
}
}
function getBarHeight ( )
{
// calculate scrollbar height and make sure it is not too small
barHeight = Math . max ( ( me . outerHeight ( ) / me [ 0 ] . scrollHeight ) * me . outerHeight ( ) , minBarHeight ) ;
bar . css ( { height : barHeight + 'px' } ) ;
// hide scrollbar if content is not long enough
var display = barHeight == me . outerHeight ( ) ? 'none' : 'block' ;
bar . css ( { display : display } ) ;
}
function showBar ( )
{
// recalculate bar height
getBarHeight ( ) ;
clearTimeout ( queueHide ) ;
// when bar reached top or bottom
if ( percentScroll == ~ ~ percentScroll )
{
//release wheel
releaseScroll = o . allowPageScroll ;
// publish approporiate event
if ( lastScroll != percentScroll )
{
var msg = ( ~ ~ percentScroll == 0 ) ? 'top' : 'bottom' ;
me . trigger ( 'slimscroll' , msg ) ;
}
}
else
{
releaseScroll = false ;
}
lastScroll = percentScroll ;
// show only when required
if ( barHeight >= me . outerHeight ( ) ) {
//allow window scroll
releaseScroll = true ;
return ;
}
bar . stop ( true , true ) . fadeIn ( 'fast' ) ;
if ( o . railVisible ) { rail . stop ( true , true ) . fadeIn ( 'fast' ) ; }
}
function hideBar ( )
{
// only hide when options allow it
if ( ! o . alwaysVisible )
{
queueHide = setTimeout ( function ( ) {
if ( ! ( o . disableFadeOut && isOverPanel ) && ! isOverBar && ! isDragg )
{
bar . fadeOut ( 'slow' ) ;
rail . fadeOut ( 'slow' ) ;
}
} , 1000 ) ;
}
}
} ) ;
// maintain chainability
return this ;
}
} ) ;
$ . fn . extend ( {
slimscroll : $ . fn . slimScroll
} ) ;
} ) ( jQuery ) ;
// This [jQuery](https://jquery.com/) plugin implements an `<iframe>`
// [transport](https://api.jquery.com/jQuery.ajax/#extending-ajax) so that
// `$.ajax()` calls support the uploading of files using standard HTML file
// input fields. This is done by switching the exchange from `XMLHttpRequest`
// to a hidden `iframe` element containing a form that is submitted.
// The [source for the plugin](https://github.com/cmlenz/jquery-iframe-transport)
// is available on [Github](https://github.com/) and licensed under the [MIT
// license](https://github.com/cmlenz/jquery-iframe-transport/blob/master/LICENSE).
// ## Usage
// To use this plugin, you simply add an `iframe` option with the value `true`
// to the Ajax settings an `$.ajax()` call, and specify the file fields to
// include in the submssion using the `files` option, which can be a selector,
// jQuery object, or a list of DOM elements containing one or more
// `<input type="file">` elements:
// $("#myform").submit(function() {
// $.ajax(this.action, {
// files: $(":file", this),
// iframe: true
// }).complete(function(data) {
// console.log(data);
// });
// });
// The plugin will construct hidden `<iframe>` and `<form>` elements, add the
// file field(s) to that form, submit the form, and process the response.
// If you want to include other form fields in the form submission, include
// them in the `data` option, and set the `processData` option to `false`:
// $("#myform").submit(function() {
// $.ajax(this.action, {
// data: $(":text", this).serializeArray(),
// files: $(":file", this),
// iframe: true,
// processData: false
// }).complete(function(data) {
// console.log(data);
// });
// });
// ### Response Data Types
// As the transport does not have access to the HTTP headers of the server
// response, it is not as simple to make use of the automatic content type
// detection provided by jQuery as with regular XHR. If you can't set the
// expected response data type (for example because it may vary depending on
// the outcome of processing by the server), you will need to employ a
// workaround on the server side: Send back an HTML document containing just a
// `<textarea>` element with a `data-type` attribute that specifies the MIME
// type, and put the actual payload in the textarea:
// <textarea data-type="application/json">
// {"ok": true, "message": "Thanks so much"}
// </textarea>
// The iframe transport plugin will detect this and pass the value of the
// `data-type` attribute on to jQuery as if it was the "Content-Type" response
// header, thereby enabling the same kind of conversions that jQuery applies
// to regular responses. For the example above you should get a Javascript
// object as the `data` parameter of the `complete` callback, with the
// properties `ok: true` and `message: "Thanks so much"`.
// ### Handling Server Errors
// Another problem with using an `iframe` for file uploads is that it is
// impossible for the javascript code to determine the HTTP status code of the
// servers response. Effectively, all of the calls you make will look like they
// are getting successful responses, and thus invoke the `done()` or
// `complete()` callbacks. You can only communicate problems using the content
// of the response payload. For example, consider using a JSON response such as
// the following to indicate a problem with an uploaded file:
// <textarea data-type="application/json">
// {"ok": false, "message": "Please only upload reasonably sized files."}
// </textarea>
// ### Compatibility
// This plugin has primarily been tested on Safari 5 (or later), Firefox 4 (or
// later), and Internet Explorer (all the way back to version 6). While I
// haven't found any issues with it so far, I'm fairly sure it still doesn't
// work around all the quirks in all different browsers. But the code is still
// pretty simple overall, so you should be able to fix it and contribute a
// patch :)
// ## Annotated Source
( function ( $ , undefined ) {
"use strict" ;
// Register a prefilter that checks whether the `iframe` option is set, and
// switches to the "iframe" data type if it is `true`.
$ . ajaxPrefilter ( function ( options , origOptions , jqXHR ) {
if ( options . iframe ) {
options . originalURL = options . url ;
return "iframe" ;
}
} ) ;
// Register a transport for the "iframe" data type. It will only activate
// when the "files" option has been set to a non-empty list of enabled file
// inputs.
$ . ajaxTransport ( "iframe" , function ( options , origOptions , jqXHR ) {
var form = null ,
iframe = null ,
name = "iframe-" + $ . now ( ) ,
files = $ ( options . files ) . filter ( ":file:enabled" ) ,
markers = null ,
accepts = null ;
// This function gets called after a successful submission or an abortion
// and should revert all changes made to the page to enable the
// submission via this transport.
function cleanUp ( ) {
files . each ( function ( i , file ) {
var $file = $ ( file ) ;
$file . data ( "clone" ) . replaceWith ( $file ) ;
} ) ;
form . remove ( ) ;
iframe . one ( "load" , function ( ) { iframe . remove ( ) ; } ) ;
iframe . attr ( "src" , "javascript:false;" ) ;
}
// Remove "iframe" from the data types list so that further processing is
// based on the content type returned by the server, without attempting an
// (unsupported) conversion from "iframe" to the actual type.
options . dataTypes . shift ( ) ;
// Use the data from the original AJAX options, as it doesn't seem to be
// copied over since jQuery 1.7.
// See https://github.com/cmlenz/jquery-iframe-transport/issues/6
options . data = origOptions . data ;
if ( files . length ) {
form = $ ( "<form enctype='multipart/form-data' method='post'></form>" ) .
hide ( ) . attr ( { action : options . originalURL , target : name } ) ;
// If there is any additional data specified via the `data` option,
// we add it as hidden fields to the form. This (currently) requires
// the `processData` option to be set to false so that the data doesn't
// get serialized to a string.
if ( typeof ( options . data ) === "string" && options . data . length > 0 ) {
$ . error ( "data must not be serialized" ) ;
}
$ . each ( options . data || { } , function ( name , value ) {
if ( $ . isPlainObject ( value ) ) {
name = value . name ;
value = value . value ;
}
$ ( "<input type='hidden' />" ) . attr ( { name : name , value : value } ) .
appendTo ( form ) ;
} ) ;
// Add a hidden `X-Requested-With` field with the value `IFrame` to the
// field, to help server-side code to determine that the upload happened
// through this transport.
$ ( "<input type='hidden' value='IFrame' name='X-Requested-With' />" ) .
appendTo ( form ) ;
// Borrowed straight from the JQuery source.
// Provides a way of specifying the accepted data type similar to the
// HTTP "Accept" header
if ( options . dataTypes [ 0 ] && options . accepts [ options . dataTypes [ 0 ] ] ) {
accepts = options . accepts [ options . dataTypes [ 0 ] ] +
( options . dataTypes [ 0 ] !== "*" ? ", */*; q=0.01" : "" ) ;
} else {
accepts = options . accepts [ "*" ] ;
}
$ ( "<input type='hidden' name='X-HTTP-Accept'>" ) .
attr ( "value" , accepts ) . appendTo ( form ) ;
// Move the file fields into the hidden form, but first remember their
// original locations in the document by replacing them with disabled
// clones. This should also avoid introducing unwanted changes to the
// page layout during submission.
markers = files . after ( function ( idx ) {
var $this = $ ( this ) ,
$clone = $this . clone ( ) . prop ( "disabled" , true ) ;
$this . data ( "clone" , $clone ) ;
return $clone ;
} ) . next ( ) ;
files . appendTo ( form ) ;
return {
// The `send` function is called by jQuery when the request should be
// sent.
send : function ( headers , completeCallback ) {
iframe = $ ( "<iframe src='javascript:false;' name='" + name +
"' id='" + name + "' style='display:none'></iframe>" ) ;
// The first load event gets fired after the iframe has been injected
// into the DOM, and is used to prepare the actual submission.
iframe . one ( "load" , function ( ) {
// The second load event gets fired when the response to the form
// submission is received. The implementation detects whether the
// actual payload is embedded in a `<textarea>` element, and
// prepares the required conversions to be made in that case.
iframe . one ( "load" , function ( ) {
var doc = this . contentWindow ? this . contentWindow . document :
( this . contentDocument ? this . contentDocument : this . document ) ,
root = doc . documentElement ? doc . documentElement : doc . body ,
textarea = root . getElementsByTagName ( "textarea" ) [ 0 ] ,
type = textarea && textarea . getAttribute ( "data-type" ) || null ,
status = textarea && textarea . getAttribute ( "data-status" ) || 200 ,
statusText = textarea && textarea . getAttribute ( "data-statusText" ) || "OK" ,
content = {
html : root . innerHTML ,
text : type ?
textarea . value :
root ? ( root . textContent || root . innerText ) : null
} ;
cleanUp ( ) ;
completeCallback ( status , statusText , content , type ?
( "Content-Type: " + type ) :
null ) ;
} ) ;
// Now that the load handler has been set up, submit the form.
form [ 0 ] . submit ( ) ;
} ) ;
// After everything has been set up correctly, the form and iframe
// get injected into the DOM so that the submission can be
// initiated.
$ ( "body" ) . append ( form , iframe ) ;
} ,
// The `abort` function is called by jQuery when the request should be
// aborted.
abort : function ( ) {
if ( iframe !== null ) {
iframe . unbind ( "load" ) . attr ( "src" , "javascript:false;" ) ;
cleanUp ( ) ;
}
}
} ;
}
} ) ;
} ) ( jQuery ) ;
/ *
* jQuery File Upload Plugin
* https : //github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010 , Sebastian Tschan
* https : //blueimp.net
*
* Licensed under the MIT license :
* https : //opensource.org/licenses/MIT
* /
/* jshint nomen:false */
/* global define, require, window, document, location, Blob, FormData */
; ( function ( factory ) {
'use strict' ;
if ( typeof define === 'function' && define . amd ) {
// Register as an anonymous AMD module:
define ( [
'jquery' ,
'jquery-ui/ui/widget'
] , factory ) ;
} else if ( typeof exports === 'object' ) {
// Node/CommonJS:
factory (
require ( 'jquery' ) ,
require ( './vendor/jquery.ui.widget' )
) ;
} else {
// Browser globals:
factory ( window . jQuery ) ;
}
} ( function ( $ ) {
'use strict' ;
// Detect file input support, based on
// http://viljamis.com/blog/2012/file-upload-support-on-mobile/
$ . support . fileInput = ! ( new RegExp (
// Handle devices which give false positives for the feature detection:
'(Android (1\\.[0156]|2\\.[01]))' +
'|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' +
'|(w(eb)?OSBrowser)|(webOS)' +
'|(Kindle/(1\\.0|2\\.[05]|3\\.0))'
) . test ( window . navigator . userAgent ) ||
// Feature detection for all other devices:
$ ( '<input type="file">' ) . prop ( 'disabled' ) ) ;
// The FileReader API is not actually used, but works as feature detection,
// as some Safari versions (5?) support XHR file uploads via the FormData API,
// but not non-multipart XHR file uploads.
// window.XMLHttpRequestUpload is not available on IE10, so we check for
// window.ProgressEvent instead to detect XHR2 file upload capability:
$ . support . xhrFileUpload = ! ! ( window . ProgressEvent && window . FileReader ) ;
$ . support . xhrFormDataFileUpload = ! ! window . FormData ;
// Detect support for Blob slicing (required for chunked uploads):
$ . support . blobSlice = window . Blob && ( Blob . prototype . slice ||
Blob . prototype . webkitSlice || Blob . prototype . mozSlice ) ;
// Helper function to create drag handlers for dragover/dragenter/dragleave:
function getDragHandler ( type ) {
var isDragOver = type === 'dragover' ;
return function ( e ) {
e . dataTransfer = e . originalEvent && e . originalEvent . dataTransfer ;
var dataTransfer = e . dataTransfer ;
if ( dataTransfer && $ . inArray ( 'Files' , dataTransfer . types ) !== - 1 &&
this . _trigger (
type ,
$ . Event ( type , { delegatedEvent : e } )
) !== false ) {
e . preventDefault ( ) ;
if ( isDragOver ) {
dataTransfer . dropEffect = 'copy' ;
}
}
} ;
}
// The fileupload widget listens for change events on file input fields defined
// via fileInput setting and paste or drop events of the given dropZone.
// In addition to the default jQuery Widget methods, the fileupload widget
// exposes the "add" and "send" methods, to add or directly send files using
// the fileupload API.
// By default, files added via file input selection, paste, drag & drop or
// "add" method are uploaded immediately, but it is possible to override
// the "add" callback option to queue file uploads.
$ . widget ( 'blueimp.fileupload' , {
options : {
// The drop target element(s), by the default the complete document.
// Set to null to disable drag & drop support:
dropZone : $ ( document ) ,
// The paste target element(s), by the default undefined.
// Set to a DOM node or jQuery object to enable file pasting:
pasteZone : undefined ,
// The file input field(s), that are listened to for change events.
// If undefined, it is set to the file input fields inside
// of the widget element on plugin initialization.
// Set to null to disable the change listener.
fileInput : undefined ,
// By default, the file input field is replaced with a clone after
// each input field change event. This is required for iframe transport
// queues and allows change events to be fired for the same file
// selection, but can be disabled by setting the following option to false:
replaceFileInput : true ,
// The parameter name for the file form data (the request argument name).
// If undefined or empty, the name property of the file input field is
// used, or "files[]" if the file input name property is also empty,
// can be a string or an array of strings:
paramName : undefined ,
// By default, each file of a selection is uploaded using an individual
// request for XHR type uploads. Set to false to upload file
// selections in one request each:
singleFileUploads : true ,
// To limit the number of files uploaded with one XHR request,
// set the following option to an integer greater than 0:
limitMultiFileUploads : undefined ,
// The following option limits the number of files uploaded with one
// XHR request to keep the request size under or equal to the defined
// limit in bytes:
limitMultiFileUploadSize : undefined ,
// Multipart file uploads add a number of bytes to each uploaded file,
// therefore the following option adds an overhead for each file used
// in the limitMultiFileUploadSize configuration:
limitMultiFileUploadSizeOverhead : 512 ,
// Set the following option to true to issue all file upload requests
// in a sequential order:
sequentialUploads : false ,
// To limit the number of concurrent uploads,
// set the following option to an integer greater than 0:
limitConcurrentUploads : undefined ,
// Set the following option to true to force iframe transport uploads:
forceIframeTransport : false ,
// Set the following option to the location of a redirect url on the
// origin server, for cross-domain iframe transport uploads:
redirect : undefined ,
// The parameter name for the redirect url, sent as part of the form
// data and set to 'redirect' if this option is empty:
redirectParamName : undefined ,
// Set the following option to the location of a postMessage window,
// to enable postMessage transport uploads:
postMessage : undefined ,
// By default, XHR file uploads are sent as multipart/form-data.
// The iframe transport is always using multipart/form-data.
// Set to false to enable non-multipart XHR uploads:
multipart : true ,
// To upload large files in smaller chunks, set the following option
// to a preferred maximum chunk size. If set to 0, null or undefined,
// or the browser does not support the required Blob API, files will
// be uploaded as a whole.
maxChunkSize : undefined ,
// When a non-multipart upload or a chunked multipart upload has been
// aborted, this option can be used to resume the upload by setting
// it to the size of the already uploaded bytes. This option is most
// useful when modifying the options object inside of the "add" or
// "send" callbacks, as the options are cloned for each file upload.
uploadedBytes : undefined ,
// By default, failed (abort or error) file uploads are removed from the
// global progress calculation. Set the following option to false to
// prevent recalculating the global progress data:
recalculateProgress : true ,
// Interval in milliseconds to calculate and trigger progress events:
progressInterval : 100 ,
// Interval in milliseconds to calculate progress bitrate:
bitrateInterval : 500 ,
// By default, uploads are started automatically when adding files:
autoUpload : true ,
// Error and info messages:
messages : {
uploadedBytes : 'Uploaded bytes exceed file size'
} ,
// Translation function, gets the message key to be translated
// and an object with context specific data as arguments:
i18n : function ( message , context ) {
message = this . messages [ message ] || message . toString ( ) ;
if ( context ) {
$ . each ( context , function ( key , value ) {
message = message . replace ( '{' + key + '}' , value ) ;
} ) ;
}
return message ;
} ,
// Additional form data to be sent along with the file uploads can be set
// using this option, which accepts an array of objects with name and
// value properties, a function returning such an array, a FormData
// object (for XHR file uploads), or a simple object.
// The form of the first fileInput is given as parameter to the function:
formData : function ( form ) {
return form . serializeArray ( ) ;
} ,
// The add callback is invoked as soon as files are added to the fileupload
// widget (via file input selection, drag & drop, paste or add API call).
// If the singleFileUploads option is enabled, this callback will be
// called once for each file in the selection for XHR file uploads, else
// once for each file selection.
//
// The upload starts when the submit method is invoked on the data parameter.
// The data object contains a files property holding the added files
// and allows you to override plugin options as well as define ajax settings.
//
// Listeners for this callback can also be bound the following way:
// .bind('fileuploadadd', func);
//
// data.submit() returns a Promise object and allows to attach additional
// handlers using jQuery's Deferred callbacks:
// data.submit().done(func).fail(func).always(func);
add : function ( e , data ) {
if ( e . isDefaultPrevented ( ) ) {
return false ;
}
if ( data . autoUpload || ( data . autoUpload !== false &&
$ ( this ) . fileupload ( 'option' , 'autoUpload' ) ) ) {
data . process ( ) . done ( function ( ) {
data . submit ( ) ;
} ) ;
}
} ,
// Other callbacks:
// Callback for the submit event of each file upload:
// submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
// Callback for the start of each file upload request:
// send: function (e, data) {}, // .bind('fileuploadsend', func);
// Callback for successful uploads:
// done: function (e, data) {}, // .bind('fileuploaddone', func);
// Callback for failed (abort or error) uploads:
// fail: function (e, data) {}, // .bind('fileuploadfail', func);
// Callback for completed (success, abort or error) requests:
// always: function (e, data) {}, // .bind('fileuploadalways', func);
// Callback for upload progress events:
// progress: function (e, data) {}, // .bind('fileuploadprogress', func);
// Callback for global upload progress events:
// progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
// Callback for uploads start, equivalent to the global ajaxStart event:
// start: function (e) {}, // .bind('fileuploadstart', func);
// Callback for uploads stop, equivalent to the global ajaxStop event:
// stop: function (e) {}, // .bind('fileuploadstop', func);
// Callback for change events of the fileInput(s):
// change: function (e, data) {}, // .bind('fileuploadchange', func);
// Callback for paste events to the pasteZone(s):
// paste: function (e, data) {}, // .bind('fileuploadpaste', func);
// Callback for drop events of the dropZone(s):
// drop: function (e, data) {}, // .bind('fileuploaddrop', func);
// Callback for dragover events of the dropZone(s):
// dragover: function (e) {}, // .bind('fileuploaddragover', func);
// Callback for the start of each chunk upload request:
// chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func);
// Callback for successful chunk uploads:
// chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func);
// Callback for failed (abort or error) chunk uploads:
// chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func);
// Callback for completed (success, abort or error) chunk upload requests:
// chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func);
// The plugin options are used as settings object for the ajax calls.
// The following are jQuery ajax settings required for the file uploads:
processData : false ,
contentType : false ,
cache : false ,
timeout : 0
} ,
// A list of options that require reinitializing event listeners and/or
// special initialization code:
_specialOptions : [
'fileInput' ,
'dropZone' ,
'pasteZone' ,
'multipart' ,
'forceIframeTransport'
] ,
_blobSlice : $ . support . blobSlice && function ( ) {
var slice = this . slice || this . webkitSlice || this . mozSlice ;
return slice . apply ( this , arguments ) ;
} ,
_BitrateTimer : function ( ) {
this . timestamp = ( ( Date . now ) ? Date . now ( ) : ( new Date ( ) ) . getTime ( ) ) ;
this . loaded = 0 ;
this . bitrate = 0 ;
this . getBitrate = function ( now , loaded , interval ) {
var timeDiff = now - this . timestamp ;
if ( ! this . bitrate || ! interval || timeDiff > interval ) {
this . bitrate = ( loaded - this . loaded ) * ( 1000 / timeDiff ) * 8 ;
this . loaded = loaded ;
this . timestamp = now ;
}
return this . bitrate ;
} ;
} ,
_isXHRUpload : function ( options ) {
return ! options . forceIframeTransport &&
( ( ! options . multipart && $ . support . xhrFileUpload ) ||
$ . support . xhrFormDataFileUpload ) ;
} ,
_getFormData : function ( options ) {
var formData ;
if ( $ . type ( options . formData ) === 'function' ) {
return options . formData ( options . form ) ;
}
if ( $ . isArray ( options . formData ) ) {
return options . formData ;
}
if ( $ . type ( options . formData ) === 'object' ) {
formData = [ ] ;
$ . each ( options . formData , function ( name , value ) {
formData . push ( { name : name , value : value } ) ;
} ) ;
return formData ;
}
return [ ] ;
} ,
_getTotal : function ( files ) {
var total = 0 ;
$ . each ( files , function ( index , file ) {
total += file . size || 1 ;
} ) ;
return total ;
} ,
_initProgressObject : function ( obj ) {
var progress = {
loaded : 0 ,
total : 0 ,
bitrate : 0
} ;
if ( obj . _progress ) {
$ . extend ( obj . _progress , progress ) ;
} else {
obj . _progress = progress ;
}
} ,
_initResponseObject : function ( obj ) {
var prop ;
if ( obj . _response ) {
for ( prop in obj . _response ) {
if ( obj . _response . hasOwnProperty ( prop ) ) {
delete obj . _response [ prop ] ;
}
}
} else {
obj . _response = { } ;
}
} ,
_onProgress : function ( e , data ) {
if ( e . lengthComputable ) {
var now = ( ( Date . now ) ? Date . now ( ) : ( new Date ( ) ) . getTime ( ) ) ,
loaded ;
if ( data . _time && data . progressInterval &&
( now - data . _time < data . progressInterval ) &&
e . loaded !== e . total ) {
return ;
}
data . _time = now ;
loaded = Math . floor (
e . loaded / e . total * ( data . chunkSize || data . _progress . total )
) + ( data . uploadedBytes || 0 ) ;
// Add the difference from the previously loaded state
// to the global loaded counter:
this . _progress . loaded += ( loaded - data . _progress . loaded ) ;
this . _progress . bitrate = this . _bitrateTimer . getBitrate (
now ,
this . _progress . loaded ,
data . bitrateInterval
) ;
data . _progress . loaded = data . loaded = loaded ;
data . _progress . bitrate = data . bitrate = data . _bitrateTimer . getBitrate (
now ,
loaded ,
data . bitrateInterval
) ;
// Trigger a custom progress event with a total data property set
// to the file size(s) of the current upload and a loaded data
// property calculated accordingly:
this . _trigger (
'progress' ,
$ . Event ( 'progress' , { delegatedEvent : e } ) ,
data
) ;
// Trigger a global progress event for all current file uploads,
// including ajax calls queued for sequential file uploads:
this . _trigger (
'progressall' ,
$ . Event ( 'progressall' , { delegatedEvent : e } ) ,
this . _progress
) ;
}
} ,
_initProgressListener : function ( options ) {
var that = this ,
xhr = options . xhr ? options . xhr ( ) : $ . ajaxSettings . xhr ( ) ;
// Accesss to the native XHR object is required to add event listeners
// for the upload progress event:
if ( xhr . upload ) {
$ ( xhr . upload ) . bind ( 'progress' , function ( e ) {
var oe = e . originalEvent ;
// Make sure the progress event properties get copied over:
e . lengthComputable = oe . lengthComputable ;
e . loaded = oe . loaded ;
e . total = oe . total ;
that . _onProgress ( e , options ) ;
} ) ;
options . xhr = function ( ) {
return xhr ;
} ;
}
} ,
_isInstanceOf : function ( type , obj ) {
// Cross-frame instanceof check
return Object . prototype . toString . call ( obj ) === '[object ' + type + ']' ;
} ,
_initXHRData : function ( options ) {
var that = this ,
formData ,
file = options . files [ 0 ] ,
// Ignore non-multipart setting if not supported:
multipart = options . multipart || ! $ . support . xhrFileUpload ,
paramName = $ . type ( options . paramName ) === 'array' ?
options . paramName [ 0 ] : options . paramName ;
options . headers = $ . extend ( { } , options . headers ) ;
if ( options . contentRange ) {
options . headers [ 'Content-Range' ] = options . contentRange ;
}
if ( ! multipart || options . blob || ! this . _isInstanceOf ( 'File' , file ) ) {
options . headers [ 'Content-Disposition' ] = 'attachment; filename="' +
2018-01-09 20:18:49 -08:00
encodeURI ( file . name ) + '"' ;
2017-12-28 20:08:45 -08:00
}
if ( ! multipart ) {
options . contentType = file . type || 'application/octet-stream' ;
options . data = options . blob || file ;
} else if ( $ . support . xhrFormDataFileUpload ) {
if ( options . postMessage ) {
// window.postMessage does not allow sending FormData
// objects, so we just add the File/Blob objects to
// the formData array and let the postMessage window
// create the FormData object out of this array:
formData = this . _getFormData ( options ) ;
if ( options . blob ) {
formData . push ( {
name : paramName ,
value : options . blob
} ) ;
} else {
$ . each ( options . files , function ( index , file ) {
formData . push ( {
name : ( $ . type ( options . paramName ) === 'array' &&
options . paramName [ index ] ) || paramName ,
value : file
} ) ;
} ) ;
}
} else {
if ( that . _isInstanceOf ( 'FormData' , options . formData ) ) {
formData = options . formData ;
} else {
formData = new FormData ( ) ;
$ . each ( this . _getFormData ( options ) , function ( index , field ) {
formData . append ( field . name , field . value ) ;
} ) ;
}
if ( options . blob ) {
2018-01-09 20:18:49 -08:00
formData . append ( paramName , options . blob , file . name ) ;
2017-12-28 20:08:45 -08:00
} else {
$ . each ( options . files , function ( index , file ) {
// This check allows the tests to run with
// dummy objects:
if ( that . _isInstanceOf ( 'File' , file ) ||
that . _isInstanceOf ( 'Blob' , file ) ) {
formData . append (
( $ . type ( options . paramName ) === 'array' &&
options . paramName [ index ] ) || paramName ,
file ,
file . uploadName || file . name
) ;
}
} ) ;
}
}
options . data = formData ;
}
// Blob reference is not needed anymore, free memory:
options . blob = null ;
} ,
_initIframeSettings : function ( options ) {
var targetHost = $ ( '<a></a>' ) . prop ( 'href' , options . url ) . prop ( 'host' ) ;
// Setting the dataType to iframe enables the iframe transport:
options . dataType = 'iframe ' + ( options . dataType || '' ) ;
// The iframe transport accepts a serialized array as form data:
options . formData = this . _getFormData ( options ) ;
// Add redirect url to form data on cross-domain uploads:
if ( options . redirect && targetHost && targetHost !== location . host ) {
options . formData . push ( {
name : options . redirectParamName || 'redirect' ,
value : options . redirect
} ) ;
}
} ,
_initDataSettings : function ( options ) {
if ( this . _isXHRUpload ( options ) ) {
if ( ! this . _chunkedUpload ( options , true ) ) {
if ( ! options . data ) {
this . _initXHRData ( options ) ;
}
this . _initProgressListener ( options ) ;
}
if ( options . postMessage ) {
// Setting the dataType to postmessage enables the
// postMessage transport:
options . dataType = 'postmessage ' + ( options . dataType || '' ) ;
}
} else {
this . _initIframeSettings ( options ) ;
}
} ,
_getParamName : function ( options ) {
var fileInput = $ ( options . fileInput ) ,
paramName = options . paramName ;
if ( ! paramName ) {
paramName = [ ] ;
fileInput . each ( function ( ) {
var input = $ ( this ) ,
name = input . prop ( 'name' ) || 'files[]' ,
i = ( input . prop ( 'files' ) || [ 1 ] ) . length ;
while ( i ) {
paramName . push ( name ) ;
i -= 1 ;
}
} ) ;
if ( ! paramName . length ) {
paramName = [ fileInput . prop ( 'name' ) || 'files[]' ] ;
}
} else if ( ! $ . isArray ( paramName ) ) {
paramName = [ paramName ] ;
}
return paramName ;
} ,
_initFormSettings : function ( options ) {
// Retrieve missing options from the input field and the
// associated form, if available:
if ( ! options . form || ! options . form . length ) {
options . form = $ ( options . fileInput . prop ( 'form' ) ) ;
// If the given file input doesn't have an associated form,
// use the default widget file input's form:
if ( ! options . form . length ) {
options . form = $ ( this . options . fileInput . prop ( 'form' ) ) ;
}
}
options . paramName = this . _getParamName ( options ) ;
if ( ! options . url ) {
options . url = options . form . prop ( 'action' ) || location . href ;
}
// The HTTP request method must be "POST" or "PUT":
options . type = ( options . type ||
( $ . type ( options . form . prop ( 'method' ) ) === 'string' &&
options . form . prop ( 'method' ) ) || ''
) . toUpperCase ( ) ;
if ( options . type !== 'POST' && options . type !== 'PUT' &&
options . type !== 'PATCH' ) {
options . type = 'POST' ;
}
if ( ! options . formAcceptCharset ) {
options . formAcceptCharset = options . form . attr ( 'accept-charset' ) ;
}
} ,
_getAJAXSettings : function ( data ) {
var options = $ . extend ( { } , this . options , data ) ;
this . _initFormSettings ( options ) ;
this . _initDataSettings ( options ) ;
return options ;
} ,
// jQuery 1.6 doesn't provide .state(),
// while jQuery 1.8+ removed .isRejected() and .isResolved():
_getDeferredState : function ( deferred ) {
if ( deferred . state ) {
return deferred . state ( ) ;
}
if ( deferred . isResolved ( ) ) {
return 'resolved' ;
}
if ( deferred . isRejected ( ) ) {
return 'rejected' ;
}
return 'pending' ;
} ,
// Maps jqXHR callbacks to the equivalent
// methods of the given Promise object:
_enhancePromise : function ( promise ) {
promise . success = promise . done ;
promise . error = promise . fail ;
promise . complete = promise . always ;
return promise ;
} ,
// Creates and returns a Promise object enhanced with
// the jqXHR methods abort, success, error and complete:
_getXHRPromise : function ( resolveOrReject , context , args ) {
var dfd = $ . Deferred ( ) ,
promise = dfd . promise ( ) ;
context = context || this . options . context || promise ;
if ( resolveOrReject === true ) {
dfd . resolveWith ( context , args ) ;
} else if ( resolveOrReject === false ) {
dfd . rejectWith ( context , args ) ;
}
promise . abort = dfd . promise ;
return this . _enhancePromise ( promise ) ;
} ,
// Adds convenience methods to the data callback argument:
_addConvenienceMethods : function ( e , data ) {
var that = this ,
getPromise = function ( args ) {
return $ . Deferred ( ) . resolveWith ( that , args ) . promise ( ) ;
} ;
data . process = function ( resolveFunc , rejectFunc ) {
if ( resolveFunc || rejectFunc ) {
data . _processQueue = this . _processQueue =
( this . _processQueue || getPromise ( [ this ] ) ) . then (
function ( ) {
if ( data . errorThrown ) {
return $ . Deferred ( )
. rejectWith ( that , [ data ] ) . promise ( ) ;
}
return getPromise ( arguments ) ;
}
) . then ( resolveFunc , rejectFunc ) ;
}
return this . _processQueue || getPromise ( [ this ] ) ;
} ;
data . submit = function ( ) {
if ( this . state ( ) !== 'pending' ) {
data . jqXHR = this . jqXHR =
( that . _trigger (
'submit' ,
$ . Event ( 'submit' , { delegatedEvent : e } ) ,
this
) !== false ) && that . _onSend ( e , this ) ;
}
return this . jqXHR || that . _getXHRPromise ( ) ;
} ;
data . abort = function ( ) {
if ( this . jqXHR ) {
return this . jqXHR . abort ( ) ;
}
this . errorThrown = 'abort' ;
that . _trigger ( 'fail' , null , this ) ;
return that . _getXHRPromise ( false ) ;
} ;
data . state = function ( ) {
if ( this . jqXHR ) {
return that . _getDeferredState ( this . jqXHR ) ;
}
if ( this . _processQueue ) {
return that . _getDeferredState ( this . _processQueue ) ;
}
} ;
data . processing = function ( ) {
return ! this . jqXHR && this . _processQueue && that
. _getDeferredState ( this . _processQueue ) === 'pending' ;
} ;
data . progress = function ( ) {
return this . _progress ;
} ;
data . response = function ( ) {
return this . _response ;
} ;
} ,
// Parses the Range header from the server response
// and returns the uploaded bytes:
_getUploadedBytes : function ( jqXHR ) {
var range = jqXHR . getResponseHeader ( 'Range' ) ,
parts = range && range . split ( '-' ) ,
upperBytesPos = parts && parts . length > 1 &&
parseInt ( parts [ 1 ] , 10 ) ;
return upperBytesPos && upperBytesPos + 1 ;
} ,
// Uploads a file in multiple, sequential requests
// by splitting the file up in multiple blob chunks.
// If the second parameter is true, only tests if the file
// should be uploaded in chunks, but does not invoke any
// upload requests:
_chunkedUpload : function ( options , testOnly ) {
options . uploadedBytes = options . uploadedBytes || 0 ;
var that = this ,
file = options . files [ 0 ] ,
fs = file . size ,
ub = options . uploadedBytes ,
mcs = options . maxChunkSize || fs ,
slice = this . _blobSlice ,
dfd = $ . Deferred ( ) ,
promise = dfd . promise ( ) ,
jqXHR ,
upload ;
if ( ! ( this . _isXHRUpload ( options ) && slice && ( ub || ( $ . type ( mcs ) === 'function' ? mcs ( options ) : mcs ) < fs ) ) ||
options . data ) {
return false ;
}
if ( testOnly ) {
return true ;
}
if ( ub >= fs ) {
file . error = options . i18n ( 'uploadedBytes' ) ;
return this . _getXHRPromise (
false ,
options . context ,
[ null , 'error' , file . error ]
) ;
}
// The chunk upload method:
upload = function ( ) {
// Clone the options object for each chunk upload:
var o = $ . extend ( { } , options ) ,
currentLoaded = o . _progress . loaded ;
o . blob = slice . call (
file ,
ub ,
ub + ( $ . type ( mcs ) === 'function' ? mcs ( o ) : mcs ) ,
file . type
) ;
// Store the current chunk size, as the blob itself
// will be dereferenced after data processing:
o . chunkSize = o . blob . size ;
// Expose the chunk bytes position range:
o . contentRange = 'bytes ' + ub + '-' +
( ub + o . chunkSize - 1 ) + '/' + fs ;
// Process the upload data (the blob and potential form data):
that . _initXHRData ( o ) ;
// Add progress listeners for this chunk upload:
that . _initProgressListener ( o ) ;
jqXHR = ( ( that . _trigger ( 'chunksend' , null , o ) !== false && $ . ajax ( o ) ) ||
that . _getXHRPromise ( false , o . context ) )
. done ( function ( result , textStatus , jqXHR ) {
ub = that . _getUploadedBytes ( jqXHR ) ||
( ub + o . chunkSize ) ;
// Create a progress event if no final progress event
// with loaded equaling total has been triggered
// for this chunk:
if ( currentLoaded + o . chunkSize - o . _progress . loaded ) {
that . _onProgress ( $ . Event ( 'progress' , {
lengthComputable : true ,
loaded : ub - o . uploadedBytes ,
total : ub - o . uploadedBytes
} ) , o ) ;
}
options . uploadedBytes = o . uploadedBytes = ub ;
o . result = result ;
o . textStatus = textStatus ;
o . jqXHR = jqXHR ;
that . _trigger ( 'chunkdone' , null , o ) ;
that . _trigger ( 'chunkalways' , null , o ) ;
if ( ub < fs ) {
// File upload not yet complete,
// continue with the next chunk:
upload ( ) ;
} else {
dfd . resolveWith (
o . context ,
[ result , textStatus , jqXHR ]
) ;
}
} )
. fail ( function ( jqXHR , textStatus , errorThrown ) {
o . jqXHR = jqXHR ;
o . textStatus = textStatus ;
o . errorThrown = errorThrown ;
that . _trigger ( 'chunkfail' , null , o ) ;
that . _trigger ( 'chunkalways' , null , o ) ;
dfd . rejectWith (
o . context ,
[ jqXHR , textStatus , errorThrown ]
) ;
} ) ;
} ;
this . _enhancePromise ( promise ) ;
promise . abort = function ( ) {
return jqXHR . abort ( ) ;
} ;
upload ( ) ;
return promise ;
} ,
_beforeSend : function ( e , data ) {
if ( this . _active === 0 ) {
// the start callback is triggered when an upload starts
// and no other uploads are currently running,
// equivalent to the global ajaxStart event:
this . _trigger ( 'start' ) ;
// Set timer for global bitrate progress calculation:
this . _bitrateTimer = new this . _BitrateTimer ( ) ;
// Reset the global progress values:
this . _progress . loaded = this . _progress . total = 0 ;
this . _progress . bitrate = 0 ;
}
// Make sure the container objects for the .response() and
// .progress() methods on the data object are available
// and reset to their initial state:
this . _initResponseObject ( data ) ;
this . _initProgressObject ( data ) ;
data . _progress . loaded = data . loaded = data . uploadedBytes || 0 ;
data . _progress . total = data . total = this . _getTotal ( data . files ) || 1 ;
data . _progress . bitrate = data . bitrate = 0 ;
this . _active += 1 ;
// Initialize the global progress values:
this . _progress . loaded += data . loaded ;
this . _progress . total += data . total ;
} ,
_onDone : function ( result , textStatus , jqXHR , options ) {
var total = options . _progress . total ,
response = options . _response ;
if ( options . _progress . loaded < total ) {
// Create a progress event if no final progress event
// with loaded equaling total has been triggered:
this . _onProgress ( $ . Event ( 'progress' , {
lengthComputable : true ,
loaded : total ,
total : total
} ) , options ) ;
}
response . result = options . result = result ;
response . textStatus = options . textStatus = textStatus ;
response . jqXHR = options . jqXHR = jqXHR ;
this . _trigger ( 'done' , null , options ) ;
} ,
_onFail : function ( jqXHR , textStatus , errorThrown , options ) {
var response = options . _response ;
if ( options . recalculateProgress ) {
// Remove the failed (error or abort) file upload from
// the global progress calculation:
this . _progress . loaded -= options . _progress . loaded ;
this . _progress . total -= options . _progress . total ;
}
response . jqXHR = options . jqXHR = jqXHR ;
response . textStatus = options . textStatus = textStatus ;
response . errorThrown = options . errorThrown = errorThrown ;
this . _trigger ( 'fail' , null , options ) ;
} ,
_onAlways : function ( jqXHRorResult , textStatus , jqXHRorError , options ) {
// jqXHRorResult, textStatus and jqXHRorError are added to the
// options object via done and fail callbacks
this . _trigger ( 'always' , null , options ) ;
} ,
_onSend : function ( e , data ) {
if ( ! data . submit ) {
this . _addConvenienceMethods ( e , data ) ;
}
var that = this ,
jqXHR ,
aborted ,
slot ,
pipe ,
options = that . _getAJAXSettings ( data ) ,
send = function ( ) {
that . _sending += 1 ;
// Set timer for bitrate progress calculation:
options . _bitrateTimer = new that . _BitrateTimer ( ) ;
jqXHR = jqXHR || (
( ( aborted || that . _trigger (
'send' ,
$ . Event ( 'send' , { delegatedEvent : e } ) ,
options
) === false ) &&
that . _getXHRPromise ( false , options . context , aborted ) ) ||
that . _chunkedUpload ( options ) || $ . ajax ( options )
) . done ( function ( result , textStatus , jqXHR ) {
that . _onDone ( result , textStatus , jqXHR , options ) ;
} ) . fail ( function ( jqXHR , textStatus , errorThrown ) {
that . _onFail ( jqXHR , textStatus , errorThrown , options ) ;
} ) . always ( function ( jqXHRorResult , textStatus , jqXHRorError ) {
that . _onAlways (
jqXHRorResult ,
textStatus ,
jqXHRorError ,
options
) ;
that . _sending -= 1 ;
that . _active -= 1 ;
if ( options . limitConcurrentUploads &&
options . limitConcurrentUploads > that . _sending ) {
// Start the next queued upload,
// that has not been aborted:
var nextSlot = that . _slots . shift ( ) ;
while ( nextSlot ) {
if ( that . _getDeferredState ( nextSlot ) === 'pending' ) {
nextSlot . resolve ( ) ;
break ;
}
nextSlot = that . _slots . shift ( ) ;
}
}
if ( that . _active === 0 ) {
// The stop callback is triggered when all uploads have
// been completed, equivalent to the global ajaxStop event:
that . _trigger ( 'stop' ) ;
}
} ) ;
return jqXHR ;
} ;
this . _beforeSend ( e , options ) ;
if ( this . options . sequentialUploads ||
( this . options . limitConcurrentUploads &&
this . options . limitConcurrentUploads <= this . _sending ) ) {
if ( this . options . limitConcurrentUploads > 1 ) {
slot = $ . Deferred ( ) ;
this . _slots . push ( slot ) ;
pipe = slot . then ( send ) ;
} else {
this . _sequence = this . _sequence . then ( send , send ) ;
pipe = this . _sequence ;
}
// Return the piped Promise object, enhanced with an abort method,
// which is delegated to the jqXHR object of the current upload,
// and jqXHR callbacks mapped to the equivalent Promise methods:
pipe . abort = function ( ) {
aborted = [ undefined , 'abort' , 'abort' ] ;
if ( ! jqXHR ) {
if ( slot ) {
slot . rejectWith ( options . context , aborted ) ;
}
return send ( ) ;
}
return jqXHR . abort ( ) ;
} ;
return this . _enhancePromise ( pipe ) ;
}
return send ( ) ;
} ,
_onAdd : function ( e , data ) {
var that = this ,
result = true ,
options = $ . extend ( { } , this . options , data ) ,
files = data . files ,
filesLength = files . length ,
limit = options . limitMultiFileUploads ,
limitSize = options . limitMultiFileUploadSize ,
overhead = options . limitMultiFileUploadSizeOverhead ,
batchSize = 0 ,
paramName = this . _getParamName ( options ) ,
paramNameSet ,
paramNameSlice ,
fileSet ,
i ,
j = 0 ;
if ( ! filesLength ) {
return false ;
}
if ( limitSize && files [ 0 ] . size === undefined ) {
limitSize = undefined ;
}
if ( ! ( options . singleFileUploads || limit || limitSize ) ||
! this . _isXHRUpload ( options ) ) {
fileSet = [ files ] ;
paramNameSet = [ paramName ] ;
} else if ( ! ( options . singleFileUploads || limitSize ) && limit ) {
fileSet = [ ] ;
paramNameSet = [ ] ;
for ( i = 0 ; i < filesLength ; i += limit ) {
fileSet . push ( files . slice ( i , i + limit ) ) ;
paramNameSlice = paramName . slice ( i , i + limit ) ;
if ( ! paramNameSlice . length ) {
paramNameSlice = paramName ;
}
paramNameSet . push ( paramNameSlice ) ;
}
} else if ( ! options . singleFileUploads && limitSize ) {
fileSet = [ ] ;
paramNameSet = [ ] ;
for ( i = 0 ; i < filesLength ; i = i + 1 ) {
batchSize += files [ i ] . size + overhead ;
if ( i + 1 === filesLength ||
( ( batchSize + files [ i + 1 ] . size + overhead ) > limitSize ) ||
( limit && i + 1 - j >= limit ) ) {
fileSet . push ( files . slice ( j , i + 1 ) ) ;
paramNameSlice = paramName . slice ( j , i + 1 ) ;
if ( ! paramNameSlice . length ) {
paramNameSlice = paramName ;
}
paramNameSet . push ( paramNameSlice ) ;
j = i + 1 ;
batchSize = 0 ;
}
}
} else {
paramNameSet = paramName ;
}
data . originalFiles = files ;
$ . each ( fileSet || files , function ( index , element ) {
var newData = $ . extend ( { } , data ) ;
newData . files = fileSet ? element : [ element ] ;
newData . paramName = paramNameSet [ index ] ;
that . _initResponseObject ( newData ) ;
that . _initProgressObject ( newData ) ;
that . _addConvenienceMethods ( e , newData ) ;
result = that . _trigger (
'add' ,
$ . Event ( 'add' , { delegatedEvent : e } ) ,
newData
) ;
return result ;
} ) ;
return result ;
} ,
_replaceFileInput : function ( data ) {
var input = data . fileInput ,
inputClone = input . clone ( true ) ,
restoreFocus = input . is ( document . activeElement ) ;
// Add a reference for the new cloned file input to the data argument:
data . fileInputClone = inputClone ;
$ ( '<form></form>' ) . append ( inputClone ) [ 0 ] . reset ( ) ;
// Detaching allows to insert the fileInput on another form
// without loosing the file input value:
input . after ( inputClone ) . detach ( ) ;
// If the fileInput had focus before it was detached,
// restore focus to the inputClone.
if ( restoreFocus ) {
inputClone . focus ( ) ;
}
// Avoid memory leaks with the detached file input:
$ . cleanData ( input . unbind ( 'remove' ) ) ;
// Replace the original file input element in the fileInput
// elements set with the clone, which has been copied including
// event handlers:
this . options . fileInput = this . options . fileInput . map ( function ( i , el ) {
if ( el === input [ 0 ] ) {
return inputClone [ 0 ] ;
}
return el ;
} ) ;
// If the widget has been initialized on the file input itself,
// override this.element with the file input clone:
if ( input [ 0 ] === this . element [ 0 ] ) {
this . element = inputClone ;
}
} ,
_handleFileTreeEntry : function ( entry , path ) {
var that = this ,
dfd = $ . Deferred ( ) ,
entries = [ ] ,
dirReader ,
errorHandler = function ( e ) {
if ( e && ! e . entry ) {
e . entry = entry ;
}
// Since $.when returns immediately if one
// Deferred is rejected, we use resolve instead.
// This allows valid files and invalid items
// to be returned together in one set:
dfd . resolve ( [ e ] ) ;
} ,
successHandler = function ( entries ) {
that . _handleFileTreeEntries (
entries ,
path + entry . name + '/'
) . done ( function ( files ) {
dfd . resolve ( files ) ;
} ) . fail ( errorHandler ) ;
} ,
readEntries = function ( ) {
dirReader . readEntries ( function ( results ) {
if ( ! results . length ) {
successHandler ( entries ) ;
} else {
entries = entries . concat ( results ) ;
readEntries ( ) ;
}
} , errorHandler ) ;
} ;
path = path || '' ;
if ( entry . isFile ) {
if ( entry . _file ) {
// Workaround for Chrome bug #149735
entry . _file . relativePath = path ;
dfd . resolve ( entry . _file ) ;
} else {
entry . file ( function ( file ) {
file . relativePath = path ;
dfd . resolve ( file ) ;
} , errorHandler ) ;
}
} else if ( entry . isDirectory ) {
dirReader = entry . createReader ( ) ;
readEntries ( ) ;
} else {
// Return an empy list for file system items
// other than files or directories:
dfd . resolve ( [ ] ) ;
}
return dfd . promise ( ) ;
} ,
_handleFileTreeEntries : function ( entries , path ) {
var that = this ;
return $ . when . apply (
$ ,
$ . map ( entries , function ( entry ) {
return that . _handleFileTreeEntry ( entry , path ) ;
} )
) . then ( function ( ) {
return Array . prototype . concat . apply (
[ ] ,
arguments
) ;
} ) ;
} ,
_getDroppedFiles : function ( dataTransfer ) {
dataTransfer = dataTransfer || { } ;
var items = dataTransfer . items ;
if ( items && items . length && ( items [ 0 ] . webkitGetAsEntry ||
items [ 0 ] . getAsEntry ) ) {
return this . _handleFileTreeEntries (
$ . map ( items , function ( item ) {
var entry ;
if ( item . webkitGetAsEntry ) {
entry = item . webkitGetAsEntry ( ) ;
if ( entry ) {
// Workaround for Chrome bug #149735:
entry . _file = item . getAsFile ( ) ;
}
return entry ;
}
return item . getAsEntry ( ) ;
} )
) ;
}
return $ . Deferred ( ) . resolve (
$ . makeArray ( dataTransfer . files )
) . promise ( ) ;
} ,
_getSingleFileInputFiles : function ( fileInput ) {
fileInput = $ ( fileInput ) ;
var entries = fileInput . prop ( 'webkitEntries' ) ||
fileInput . prop ( 'entries' ) ,
files ,
value ;
if ( entries && entries . length ) {
return this . _handleFileTreeEntries ( entries ) ;
}
files = $ . makeArray ( fileInput . prop ( 'files' ) ) ;
if ( ! files . length ) {
value = fileInput . prop ( 'value' ) ;
if ( ! value ) {
return $ . Deferred ( ) . resolve ( [ ] ) . promise ( ) ;
}
// If the files property is not available, the browser does not
// support the File API and we add a pseudo File object with
// the input value as name with path information removed:
files = [ { name : value . replace ( /^.*\\/ , '' ) } ] ;
} else if ( files [ 0 ] . name === undefined && files [ 0 ] . fileName ) {
// File normalization for Safari 4 and Firefox 3:
$ . each ( files , function ( index , file ) {
file . name = file . fileName ;
file . size = file . fileSize ;
} ) ;
}
return $ . Deferred ( ) . resolve ( files ) . promise ( ) ;
} ,
_getFileInputFiles : function ( fileInput ) {
if ( ! ( fileInput instanceof $ ) || fileInput . length === 1 ) {
return this . _getSingleFileInputFiles ( fileInput ) ;
}
return $ . when . apply (
$ ,
$ . map ( fileInput , this . _getSingleFileInputFiles )
) . then ( function ( ) {
return Array . prototype . concat . apply (
[ ] ,
arguments
) ;
} ) ;
} ,
_onChange : function ( e ) {
var that = this ,
data = {
fileInput : $ ( e . target ) ,
form : $ ( e . target . form )
} ;
this . _getFileInputFiles ( data . fileInput ) . always ( function ( files ) {
data . files = files ;
if ( that . options . replaceFileInput ) {
that . _replaceFileInput ( data ) ;
}
if ( that . _trigger (
'change' ,
$ . Event ( 'change' , { delegatedEvent : e } ) ,
data
) !== false ) {
that . _onAdd ( e , data ) ;
}
} ) ;
} ,
_onPaste : function ( e ) {
var items = e . originalEvent && e . originalEvent . clipboardData &&
e . originalEvent . clipboardData . items ,
data = { files : [ ] } ;
if ( items && items . length ) {
$ . each ( items , function ( index , item ) {
var file = item . getAsFile && item . getAsFile ( ) ;
if ( file ) {
data . files . push ( file ) ;
}
} ) ;
if ( this . _trigger (
'paste' ,
$ . Event ( 'paste' , { delegatedEvent : e } ) ,
data
) !== false ) {
this . _onAdd ( e , data ) ;
}
}
} ,
_onDrop : function ( e ) {
e . dataTransfer = e . originalEvent && e . originalEvent . dataTransfer ;
var that = this ,
dataTransfer = e . dataTransfer ,
data = { } ;
if ( dataTransfer && dataTransfer . files && dataTransfer . files . length ) {
e . preventDefault ( ) ;
this . _getDroppedFiles ( dataTransfer ) . always ( function ( files ) {
data . files = files ;
if ( that . _trigger (
'drop' ,
$ . Event ( 'drop' , { delegatedEvent : e } ) ,
data
) !== false ) {
that . _onAdd ( e , data ) ;
}
} ) ;
}
} ,
_onDragOver : getDragHandler ( 'dragover' ) ,
_onDragEnter : getDragHandler ( 'dragenter' ) ,
_onDragLeave : getDragHandler ( 'dragleave' ) ,
_initEventHandlers : function ( ) {
if ( this . _isXHRUpload ( this . options ) ) {
this . _on ( this . options . dropZone , {
dragover : this . _onDragOver ,
drop : this . _onDrop ,
// event.preventDefault() on dragenter is required for IE10+:
dragenter : this . _onDragEnter ,
// dragleave is not required, but added for completeness:
dragleave : this . _onDragLeave
} ) ;
this . _on ( this . options . pasteZone , {
paste : this . _onPaste
} ) ;
}
if ( $ . support . fileInput ) {
this . _on ( this . options . fileInput , {
change : this . _onChange
} ) ;
}
} ,
_destroyEventHandlers : function ( ) {
this . _off ( this . options . dropZone , 'dragenter dragleave dragover drop' ) ;
this . _off ( this . options . pasteZone , 'paste' ) ;
this . _off ( this . options . fileInput , 'change' ) ;
} ,
_destroy : function ( ) {
this . _destroyEventHandlers ( ) ;
} ,
_setOption : function ( key , value ) {
var reinit = $ . inArray ( key , this . _specialOptions ) !== - 1 ;
if ( reinit ) {
this . _destroyEventHandlers ( ) ;
}
this . _super ( key , value ) ;
if ( reinit ) {
this . _initSpecialOptions ( ) ;
this . _initEventHandlers ( ) ;
}
} ,
_initSpecialOptions : function ( ) {
var options = this . options ;
if ( options . fileInput === undefined ) {
options . fileInput = this . element . is ( 'input[type="file"]' ) ?
this . element : this . element . find ( 'input[type="file"]' ) ;
} else if ( ! ( options . fileInput instanceof $ ) ) {
options . fileInput = $ ( options . fileInput ) ;
}
if ( ! ( options . dropZone instanceof $ ) ) {
options . dropZone = $ ( options . dropZone ) ;
}
if ( ! ( options . pasteZone instanceof $ ) ) {
options . pasteZone = $ ( options . pasteZone ) ;
}
} ,
_getRegExp : function ( str ) {
var parts = str . split ( '/' ) ,
modifiers = parts . pop ( ) ;
parts . shift ( ) ;
return new RegExp ( parts . join ( '/' ) , modifiers ) ;
} ,
_isRegExpOption : function ( key , value ) {
return key !== 'url' && $ . type ( value ) === 'string' &&
/^\/.*\/[igm]{0,3}$/ . test ( value ) ;
} ,
_initDataAttributes : function ( ) {
var that = this ,
options = this . options ,
data = this . element . data ( ) ;
// Initialize options set via HTML5 data-attributes:
$ . each (
this . element [ 0 ] . attributes ,
function ( index , attr ) {
var key = attr . name . toLowerCase ( ) ,
value ;
if ( /^data-/ . test ( key ) ) {
// Convert hyphen-ated key to camelCase:
key = key . slice ( 5 ) . replace ( /-[a-z]/g , function ( str ) {
return str . charAt ( 1 ) . toUpperCase ( ) ;
} ) ;
value = data [ key ] ;
if ( that . _isRegExpOption ( key , value ) ) {
value = that . _getRegExp ( value ) ;
}
options [ key ] = value ;
}
}
) ;
} ,
_create : function ( ) {
this . _initDataAttributes ( ) ;
this . _initSpecialOptions ( ) ;
this . _slots = [ ] ;
this . _sequence = this . _getXHRPromise ( true ) ;
this . _sending = this . _active = 0 ;
this . _initProgressObject ( this ) ;
this . _initEventHandlers ( ) ;
} ,
// This method is exposed to the widget API and allows to query
// the number of active uploads:
active : function ( ) {
return this . _active ;
} ,
// This method is exposed to the widget API and allows to query
// the widget upload progress.
// It returns an object with loaded, total and bitrate properties
// for the running uploads:
progress : function ( ) {
return this . _progress ;
} ,
// This method is exposed to the widget API and allows adding files
// using the fileupload API. The data parameter accepts an object which
// must have a files property and can contain additional options:
// .fileupload('add', {files: filesList});
add : function ( data ) {
var that = this ;
if ( ! data || this . options . disabled ) {
return ;
}
if ( data . fileInput && ! data . files ) {
this . _getFileInputFiles ( data . fileInput ) . always ( function ( files ) {
data . files = files ;
that . _onAdd ( null , data ) ;
} ) ;
} else {
data . files = $ . makeArray ( data . files ) ;
this . _onAdd ( null , data ) ;
}
} ,
// This method is exposed to the widget API and allows sending files
// using the fileupload API. The data parameter accepts an object which
// must have a files or fileInput property and can contain additional options:
// .fileupload('send', {files: filesList});
// The method returns a Promise object for the file upload call.
send : function ( data ) {
if ( data && ! this . options . disabled ) {
if ( data . fileInput && ! data . files ) {
var that = this ,
dfd = $ . Deferred ( ) ,
promise = dfd . promise ( ) ,
jqXHR ,
aborted ;
promise . abort = function ( ) {
aborted = true ;
if ( jqXHR ) {
return jqXHR . abort ( ) ;
}
dfd . reject ( null , 'abort' , 'abort' ) ;
return promise ;
} ;
this . _getFileInputFiles ( data . fileInput ) . always (
function ( files ) {
if ( aborted ) {
return ;
}
if ( ! files . length ) {
dfd . reject ( ) ;
return ;
}
data . files = files ;
jqXHR = that . _onSend ( null , data ) ;
jqXHR . then (
function ( result , textStatus , jqXHR ) {
dfd . resolve ( result , textStatus , jqXHR ) ;
} ,
function ( jqXHR , textStatus , errorThrown ) {
dfd . reject ( jqXHR , textStatus , errorThrown ) ;
}
) ;
}
) ;
return this . _enhancePromise ( promise ) ;
}
data . files = $ . makeArray ( data . files ) ;
if ( data . files . length ) {
return this . _onSend ( null , data ) ;
}
}
return this . _getXHRPromise ( false , data && data . context ) ;
}
} ) ;
} ) ) ;
/ * !
* Bootstrap Colorpicker v2 . 5.2
* https : //itsjavi.com/bootstrap-colorpicker/
*
* Originally written by ( c ) 2012 Stefan Petre
* Licensed under the Apache License v2 . 0
* http : //www.apache.org/licenses/LICENSE-2.0.txt
*
* /
( function ( root , factory ) {
if ( typeof define === 'function' && define . amd ) {
// AMD. Register as an anonymous module unless amdModuleId is set
define ( [ "jquery" ] , function ( jq ) {
return ( factory ( jq ) ) ;
} ) ;
} else if ( typeof exports === 'object' ) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module . exports = factory ( require ( "jquery" ) ) ;
} else if ( jQuery && ! jQuery . fn . colorpicker ) {
factory ( jQuery ) ;
}
} ( this , function ( $ ) {
'use strict' ;
/ * *
* Color manipulation helper class
*
* @ param { Object | String } [ val ]
* @ param { Object } [ predefinedColors ]
* @ param { String | null } [ fallbackColor ]
* @ param { String | null } [ fallbackFormat ]
* @ param { Boolean } [ hexNumberSignPrefix ]
* @ constructor
* /
var Color = function (
val , predefinedColors , fallbackColor , fallbackFormat , hexNumberSignPrefix ) {
this . fallbackValue = fallbackColor ?
(
fallbackColor && ( typeof fallbackColor . h !== 'undefined' ) ?
fallbackColor :
this . value = {
h : 0 ,
s : 0 ,
b : 0 ,
a : 1
}
) :
null ;
this . fallbackFormat = fallbackFormat ? fallbackFormat : 'rgba' ;
this . hexNumberSignPrefix = hexNumberSignPrefix === true ;
this . value = this . fallbackValue ;
this . origFormat = null ; // original string format
this . predefinedColors = predefinedColors ? predefinedColors : { } ;
// We don't want to share aliases across instances so we extend new object
this . colors = $ . extend ( { } , Color . webColors , this . predefinedColors ) ;
if ( val ) {
if ( typeof val . h !== 'undefined' ) {
this . value = val ;
} else {
this . setColor ( String ( val ) ) ;
}
}
if ( ! this . value ) {
// Initial value is always black if no arguments are passed or val is empty
this . value = {
h : 0 ,
s : 0 ,
b : 0 ,
a : 1
} ;
}
} ;
Color . webColors = { // 140 predefined colors from the HTML Colors spec
"aliceblue" : "f0f8ff" ,
"antiquewhite" : "faebd7" ,
"aqua" : "00ffff" ,
"aquamarine" : "7fffd4" ,
"azure" : "f0ffff" ,
"beige" : "f5f5dc" ,
"bisque" : "ffe4c4" ,
"black" : "000000" ,
"blanchedalmond" : "ffebcd" ,
"blue" : "0000ff" ,
"blueviolet" : "8a2be2" ,
"brown" : "a52a2a" ,
"burlywood" : "deb887" ,
"cadetblue" : "5f9ea0" ,
"chartreuse" : "7fff00" ,
"chocolate" : "d2691e" ,
"coral" : "ff7f50" ,
"cornflowerblue" : "6495ed" ,
"cornsilk" : "fff8dc" ,
"crimson" : "dc143c" ,
"cyan" : "00ffff" ,
"darkblue" : "00008b" ,
"darkcyan" : "008b8b" ,
"darkgoldenrod" : "b8860b" ,
"darkgray" : "a9a9a9" ,
"darkgreen" : "006400" ,
"darkkhaki" : "bdb76b" ,
"darkmagenta" : "8b008b" ,
"darkolivegreen" : "556b2f" ,
"darkorange" : "ff8c00" ,
"darkorchid" : "9932cc" ,
"darkred" : "8b0000" ,
"darksalmon" : "e9967a" ,
"darkseagreen" : "8fbc8f" ,
"darkslateblue" : "483d8b" ,
"darkslategray" : "2f4f4f" ,
"darkturquoise" : "00ced1" ,
"darkviolet" : "9400d3" ,
"deeppink" : "ff1493" ,
"deepskyblue" : "00bfff" ,
"dimgray" : "696969" ,
"dodgerblue" : "1e90ff" ,
"firebrick" : "b22222" ,
"floralwhite" : "fffaf0" ,
"forestgreen" : "228b22" ,
"fuchsia" : "ff00ff" ,
"gainsboro" : "dcdcdc" ,
"ghostwhite" : "f8f8ff" ,
"gold" : "ffd700" ,
"goldenrod" : "daa520" ,
"gray" : "808080" ,
"green" : "008000" ,
"greenyellow" : "adff2f" ,
"honeydew" : "f0fff0" ,
"hotpink" : "ff69b4" ,
"indianred" : "cd5c5c" ,
"indigo" : "4b0082" ,
"ivory" : "fffff0" ,
"khaki" : "f0e68c" ,
"lavender" : "e6e6fa" ,
"lavenderblush" : "fff0f5" ,
"lawngreen" : "7cfc00" ,
"lemonchiffon" : "fffacd" ,
"lightblue" : "add8e6" ,
"lightcoral" : "f08080" ,
"lightcyan" : "e0ffff" ,
"lightgoldenrodyellow" : "fafad2" ,
"lightgrey" : "d3d3d3" ,
"lightgreen" : "90ee90" ,
"lightpink" : "ffb6c1" ,
"lightsalmon" : "ffa07a" ,
"lightseagreen" : "20b2aa" ,
"lightskyblue" : "87cefa" ,
"lightslategray" : "778899" ,
"lightsteelblue" : "b0c4de" ,
"lightyellow" : "ffffe0" ,
"lime" : "00ff00" ,
"limegreen" : "32cd32" ,
"linen" : "faf0e6" ,
"magenta" : "ff00ff" ,
"maroon" : "800000" ,
"mediumaquamarine" : "66cdaa" ,
"mediumblue" : "0000cd" ,
"mediumorchid" : "ba55d3" ,
"mediumpurple" : "9370d8" ,
"mediumseagreen" : "3cb371" ,
"mediumslateblue" : "7b68ee" ,
"mediumspringgreen" : "00fa9a" ,
"mediumturquoise" : "48d1cc" ,
"mediumvioletred" : "c71585" ,
"midnightblue" : "191970" ,
"mintcream" : "f5fffa" ,
"mistyrose" : "ffe4e1" ,
"moccasin" : "ffe4b5" ,
"navajowhite" : "ffdead" ,
"navy" : "000080" ,
"oldlace" : "fdf5e6" ,
"olive" : "808000" ,
"olivedrab" : "6b8e23" ,
"orange" : "ffa500" ,
"orangered" : "ff4500" ,
"orchid" : "da70d6" ,
"palegoldenrod" : "eee8aa" ,
"palegreen" : "98fb98" ,
"paleturquoise" : "afeeee" ,
"palevioletred" : "d87093" ,
"papayawhip" : "ffefd5" ,
"peachpuff" : "ffdab9" ,
"peru" : "cd853f" ,
"pink" : "ffc0cb" ,
"plum" : "dda0dd" ,
"powderblue" : "b0e0e6" ,
"purple" : "800080" ,
"red" : "ff0000" ,
"rosybrown" : "bc8f8f" ,
"royalblue" : "4169e1" ,
"saddlebrown" : "8b4513" ,
"salmon" : "fa8072" ,
"sandybrown" : "f4a460" ,
"seagreen" : "2e8b57" ,
"seashell" : "fff5ee" ,
"sienna" : "a0522d" ,
"silver" : "c0c0c0" ,
"skyblue" : "87ceeb" ,
"slateblue" : "6a5acd" ,
"slategray" : "708090" ,
"snow" : "fffafa" ,
"springgreen" : "00ff7f" ,
"steelblue" : "4682b4" ,
"tan" : "d2b48c" ,
"teal" : "008080" ,
"thistle" : "d8bfd8" ,
"tomato" : "ff6347" ,
"turquoise" : "40e0d0" ,
"violet" : "ee82ee" ,
"wheat" : "f5deb3" ,
"white" : "ffffff" ,
"whitesmoke" : "f5f5f5" ,
"yellow" : "ffff00" ,
"yellowgreen" : "9acd32" ,
"transparent" : "transparent"
} ;
Color . prototype = {
constructor : Color ,
colors : { } , // merged web and predefined colors
predefinedColors : { } ,
/ * *
* @ return { Object }
* /
getValue : function ( ) {
return this . value ;
} ,
/ * *
* @ param { Object } val
* /
setValue : function ( val ) {
this . value = val ;
} ,
_sanitizeNumber : function ( val ) {
if ( typeof val === 'number' ) {
return val ;
}
if ( isNaN ( val ) || ( val === null ) || ( val === '' ) || ( val === undefined ) ) {
return 1 ;
}
if ( val === '' ) {
return 0 ;
}
if ( typeof val . toLowerCase !== 'undefined' ) {
if ( val . match ( /^\./ ) ) {
val = "0" + val ;
}
return Math . ceil ( parseFloat ( val ) * 100 ) / 100 ;
}
return 1 ;
} ,
isTransparent : function ( strVal ) {
if ( ! strVal || ! ( typeof strVal === 'string' || strVal instanceof String ) ) {
return false ;
}
strVal = strVal . toLowerCase ( ) . trim ( ) ;
return ( strVal === 'transparent' ) || ( strVal . match ( /#?00000000/ ) ) || ( strVal . match ( /(rgba|hsla)\(0,0,0,0?\.?0\)/ ) ) ;
} ,
rgbaIsTransparent : function ( rgba ) {
return ( ( rgba . r === 0 ) && ( rgba . g === 0 ) && ( rgba . b === 0 ) && ( rgba . a === 0 ) ) ;
} ,
// parse a string to HSB
/ * *
* @ protected
* @ param { String } strVal
* @ returns { boolean } Returns true if it could be parsed , false otherwise
* /
setColor : function ( strVal ) {
strVal = strVal . toLowerCase ( ) . trim ( ) ;
if ( strVal ) {
if ( this . isTransparent ( strVal ) ) {
this . value = {
h : 0 ,
s : 0 ,
b : 0 ,
a : 0
} ;
return true ;
} else {
var parsedColor = this . parse ( strVal ) ;
if ( parsedColor ) {
this . value = this . value = {
h : parsedColor . h ,
s : parsedColor . s ,
b : parsedColor . b ,
a : parsedColor . a
} ;
if ( ! this . origFormat ) {
this . origFormat = parsedColor . format ;
}
} else if ( this . fallbackValue ) {
// if parser fails, defaults to fallbackValue if defined, otherwise the value won't be changed
this . value = this . fallbackValue ;
}
}
}
return false ;
} ,
setHue : function ( h ) {
this . value . h = 1 - h ;
} ,
setSaturation : function ( s ) {
this . value . s = s ;
} ,
setBrightness : function ( b ) {
this . value . b = 1 - b ;
} ,
setAlpha : function ( a ) {
this . value . a = Math . round ( ( parseInt ( ( 1 - a ) * 100 , 10 ) / 100 ) * 100 ) / 100 ;
} ,
toRGB : function ( h , s , b , a ) {
if ( arguments . length === 0 ) {
h = this . value . h ;
s = this . value . s ;
b = this . value . b ;
a = this . value . a ;
}
h *= 360 ;
var R , G , B , X , C ;
h = ( h % 360 ) / 60 ;
C = b * s ;
X = C * ( 1 - Math . abs ( h % 2 - 1 ) ) ;
R = G = B = b - C ;
h = ~ ~ h ;
R += [ C , X , 0 , 0 , X , C ] [ h ] ;
G += [ X , C , C , X , 0 , 0 ] [ h ] ;
B += [ 0 , 0 , X , C , C , X ] [ h ] ;
return {
r : Math . round ( R * 255 ) ,
g : Math . round ( G * 255 ) ,
b : Math . round ( B * 255 ) ,
a : a
} ;
} ,
toHex : function ( ignoreFormat , h , s , b , a ) {
if ( arguments . length <= 1 ) {
h = this . value . h ;
s = this . value . s ;
b = this . value . b ;
a = this . value . a ;
}
var prefix = '#' ;
var rgb = this . toRGB ( h , s , b , a ) ;
if ( this . rgbaIsTransparent ( rgb ) ) {
return 'transparent' ;
}
if ( ! ignoreFormat ) {
prefix = ( this . hexNumberSignPrefix ? '#' : '' ) ;
}
var hexStr = prefix + (
( 1 << 24 ) +
( parseInt ( rgb . r ) << 16 ) +
( parseInt ( rgb . g ) << 8 ) +
parseInt ( rgb . b ) )
. toString ( 16 )
. slice ( 1 ) ;
return hexStr ;
} ,
toHSL : function ( h , s , b , a ) {
if ( arguments . length === 0 ) {
h = this . value . h ;
s = this . value . s ;
b = this . value . b ;
a = this . value . a ;
}
var H = h ,
L = ( 2 - s ) * b ,
S = s * b ;
if ( L > 0 && L <= 1 ) {
S /= L ;
} else {
S /= 2 - L ;
}
L /= 2 ;
if ( S > 1 ) {
S = 1 ;
}
return {
h : isNaN ( H ) ? 0 : H ,
s : isNaN ( S ) ? 0 : S ,
l : isNaN ( L ) ? 0 : L ,
a : isNaN ( a ) ? 0 : a
} ;
} ,
toAlias : function ( r , g , b , a ) {
var c , rgb = ( arguments . length === 0 ) ? this . toHex ( true ) : this . toHex ( true , r , g , b , a ) ;
// support predef. colors in non-hex format too, as defined in the alias itself
var original = this . origFormat === 'alias' ? rgb : this . toString ( false , this . origFormat ) ;
for ( var alias in this . colors ) {
c = this . colors [ alias ] . toLowerCase ( ) . trim ( ) ;
if ( ( c === rgb ) || ( c === original ) ) {
return alias ;
}
}
return false ;
} ,
RGBtoHSB : function ( r , g , b , a ) {
r /= 255 ;
g /= 255 ;
b /= 255 ;
var H , S , V , C ;
V = Math . max ( r , g , b ) ;
C = V - Math . min ( r , g , b ) ;
H = ( C === 0 ? null :
V === r ? ( g - b ) / C :
V === g ? ( b - r ) / C + 2 :
( r - g ) / C + 4
) ;
H = ( ( H + 360 ) % 6 ) * 60 / 360 ;
S = C === 0 ? 0 : C / V ;
return {
h : this . _sanitizeNumber ( H ) ,
s : S ,
b : V ,
a : this . _sanitizeNumber ( a )
} ;
} ,
HueToRGB : function ( p , q , h ) {
if ( h < 0 ) {
h += 1 ;
} else if ( h > 1 ) {
h -= 1 ;
}
if ( ( h * 6 ) < 1 ) {
return p + ( q - p ) * h * 6 ;
} else if ( ( h * 2 ) < 1 ) {
return q ;
} else if ( ( h * 3 ) < 2 ) {
return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6 ;
} else {
return p ;
}
} ,
HSLtoRGB : function ( h , s , l , a ) {
if ( s < 0 ) {
s = 0 ;
}
var q ;
if ( l <= 0.5 ) {
q = l * ( 1 + s ) ;
} else {
q = l + s - ( l * s ) ;
}
var p = 2 * l - q ;
var tr = h + ( 1 / 3 ) ;
var tg = h ;
var tb = h - ( 1 / 3 ) ;
var r = Math . round ( this . HueToRGB ( p , q , tr ) * 255 ) ;
var g = Math . round ( this . HueToRGB ( p , q , tg ) * 255 ) ;
var b = Math . round ( this . HueToRGB ( p , q , tb ) * 255 ) ;
return [ r , g , b , this . _sanitizeNumber ( a ) ] ;
} ,
/ * *
* @ param { String } strVal
* @ returns { Object } Object containing h , s , b , a , format properties or FALSE if failed to parse
* /
parse : function ( strVal ) {
if ( arguments . length === 0 ) {
return false ;
}
var that = this ,
result = false ,
isAlias = ( typeof this . colors [ strVal ] !== 'undefined' ) ,
values , format ;
if ( isAlias ) {
strVal = this . colors [ strVal ] . toLowerCase ( ) . trim ( ) ;
}
$ . each ( this . stringParsers , function ( i , parser ) {
var match = parser . re . exec ( strVal ) ;
values = match && parser . parse . apply ( that , [ match ] ) ;
if ( values ) {
result = { } ;
format = ( isAlias ? 'alias' : ( parser . format ? parser . format : that . getValidFallbackFormat ( ) ) ) ;
if ( format . match ( /hsla?/ ) ) {
result = that . RGBtoHSB . apply ( that , that . HSLtoRGB . apply ( that , values ) ) ;
} else {
result = that . RGBtoHSB . apply ( that , values ) ;
}
if ( result instanceof Object ) {
result . format = format ;
}
return false ; // stop iterating
}
return true ;
} ) ;
return result ;
} ,
getValidFallbackFormat : function ( ) {
var formats = [
'rgba' , 'rgb' , 'hex' , 'hsla' , 'hsl'
] ;
if ( this . origFormat && ( formats . indexOf ( this . origFormat ) !== - 1 ) ) {
return this . origFormat ;
}
if ( this . fallbackFormat && ( formats . indexOf ( this . fallbackFormat ) !== - 1 ) ) {
return this . fallbackFormat ;
}
return 'rgba' ; // By default, return a format that will not lose the alpha info
} ,
/ * *
*
* @ param { string } [ format ] ( default : rgba )
* @ param { boolean } [ translateAlias ] Return real color for pre - defined ( non - standard ) aliases ( default : false )
* @ param { boolean } [ forceRawValue ] Forces hashtag prefix when getting hex color ( default : false )
* @ returns { String }
* /
toString : function ( forceRawValue , format , translateAlias ) {
format = format || this . origFormat || this . fallbackFormat ;
translateAlias = translateAlias || false ;
var c = false ;
switch ( format ) {
case 'rgb' :
{
c = this . toRGB ( ) ;
if ( this . rgbaIsTransparent ( c ) ) {
return 'transparent' ;
}
return 'rgb(' + c . r + ',' + c . g + ',' + c . b + ')' ;
}
break ;
case 'rgba' :
{
c = this . toRGB ( ) ;
return 'rgba(' + c . r + ',' + c . g + ',' + c . b + ',' + c . a + ')' ;
}
break ;
case 'hsl' :
{
c = this . toHSL ( ) ;
return 'hsl(' + Math . round ( c . h * 360 ) + ',' + Math . round ( c . s * 100 ) + '%,' + Math . round ( c . l * 100 ) + '%)' ;
}
break ;
case 'hsla' :
{
c = this . toHSL ( ) ;
return 'hsla(' + Math . round ( c . h * 360 ) + ',' + Math . round ( c . s * 100 ) + '%,' + Math . round ( c . l * 100 ) + '%,' + c . a + ')' ;
}
break ;
case 'hex' :
{
return this . toHex ( forceRawValue ) ;
}
break ;
case 'alias' :
{
c = this . toAlias ( ) ;
if ( c === false ) {
return this . toString ( forceRawValue , this . getValidFallbackFormat ( ) ) ;
}
if ( translateAlias && ! ( c in Color . webColors ) && ( c in this . predefinedColors ) ) {
return this . predefinedColors [ c ] ;
}
return c ;
}
default :
{
return c ;
}
break ;
}
} ,
// a set of RE's that can match strings and generate color tuples.
// from John Resig color plugin
// https://github.com/jquery/jquery-color/
stringParsers : [ {
re : /rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*?\)/ ,
format : 'rgb' ,
parse : function ( execResult ) {
return [
execResult [ 1 ] ,
execResult [ 2 ] ,
execResult [ 3 ] ,
1
] ;
}
} , {
re : /rgb\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/ ,
format : 'rgb' ,
parse : function ( execResult ) {
return [
2.55 * execResult [ 1 ] ,
2.55 * execResult [ 2 ] ,
2.55 * execResult [ 3 ] ,
1
] ;
}
} , {
re : /rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/ ,
format : 'rgba' ,
parse : function ( execResult ) {
return [
execResult [ 1 ] ,
execResult [ 2 ] ,
execResult [ 3 ] ,
execResult [ 4 ]
] ;
}
} , {
re : /rgba\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/ ,
format : 'rgba' ,
parse : function ( execResult ) {
return [
2.55 * execResult [ 1 ] ,
2.55 * execResult [ 2 ] ,
2.55 * execResult [ 3 ] ,
execResult [ 4 ]
] ;
}
} , {
re : /hsl\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/ ,
format : 'hsl' ,
parse : function ( execResult ) {
return [
execResult [ 1 ] / 360 ,
execResult [ 2 ] / 100 ,
execResult [ 3 ] / 100 ,
execResult [ 4 ]
] ;
}
} , {
re : /hsla\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/ ,
format : 'hsla' ,
parse : function ( execResult ) {
return [
execResult [ 1 ] / 360 ,
execResult [ 2 ] / 100 ,
execResult [ 3 ] / 100 ,
execResult [ 4 ]
] ;
}
} , {
re : /#?([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/ ,
format : 'hex' ,
parse : function ( execResult ) {
return [
parseInt ( execResult [ 1 ] , 16 ) ,
parseInt ( execResult [ 2 ] , 16 ) ,
parseInt ( execResult [ 3 ] , 16 ) ,
1
] ;
}
} , {
re : /#?([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/ ,
format : 'hex' ,
parse : function ( execResult ) {
return [
parseInt ( execResult [ 1 ] + execResult [ 1 ] , 16 ) ,
parseInt ( execResult [ 2 ] + execResult [ 2 ] , 16 ) ,
parseInt ( execResult [ 3 ] + execResult [ 3 ] , 16 ) ,
1
] ;
}
} ] ,
colorNameToHex : function ( name ) {
if ( typeof this . colors [ name . toLowerCase ( ) ] !== 'undefined' ) {
return this . colors [ name . toLowerCase ( ) ] ;
}
return false ;
}
} ;
/ *
* Default plugin options
* /
var defaults = {
horizontal : false , // horizontal mode layout ?
inline : false , //forces to show the colorpicker as an inline element
color : false , //forces a color
format : false , //forces a format
input : 'input' , // children input selector
container : false , // container selector
component : '.add-on, .input-group-addon' , // children component selector
fallbackColor : false , // fallback color value. null = keeps current color.
fallbackFormat : 'hex' , // fallback color format
hexNumberSignPrefix : true , // put a '#' (number sign) before hex strings
sliders : {
saturation : {
maxLeft : 100 ,
maxTop : 100 ,
callLeft : 'setSaturation' ,
callTop : 'setBrightness'
} ,
hue : {
maxLeft : 0 ,
maxTop : 100 ,
callLeft : false ,
callTop : 'setHue'
} ,
alpha : {
maxLeft : 0 ,
maxTop : 100 ,
callLeft : false ,
callTop : 'setAlpha'
}
} ,
slidersHorz : {
saturation : {
maxLeft : 100 ,
maxTop : 100 ,
callLeft : 'setSaturation' ,
callTop : 'setBrightness'
} ,
hue : {
maxLeft : 100 ,
maxTop : 0 ,
callLeft : 'setHue' ,
callTop : false
} ,
alpha : {
maxLeft : 100 ,
maxTop : 0 ,
callLeft : 'setAlpha' ,
callTop : false
}
} ,
template : '<div class="colorpicker dropdown-menu">' +
'<div class="colorpicker-saturation"><i><b></b></i></div>' +
'<div class="colorpicker-hue"><i></i></div>' +
'<div class="colorpicker-alpha"><i></i></div>' +
'<div class="colorpicker-color"><div /></div>' +
'<div class="colorpicker-selectors"></div>' +
'</div>' ,
align : 'right' ,
customClass : null , // custom class added to the colorpicker element
colorSelectors : null // custom color aliases
} ;
/ * *
* Colorpicker component class
*
* @ param { Object | String } element
* @ param { Object } options
* @ constructor
* /
var Colorpicker = function ( element , options ) {
this . element = $ ( element ) . addClass ( 'colorpicker-element' ) ;
this . options = $ . extend ( true , { } , defaults , this . element . data ( ) , options ) ;
this . component = this . options . component ;
this . component = ( this . component !== false ) ? this . element . find ( this . component ) : false ;
if ( this . component && ( this . component . length === 0 ) ) {
this . component = false ;
}
this . container = ( this . options . container === true ) ? this . element : this . options . container ;
this . container = ( this . container !== false ) ? $ ( this . container ) : false ;
// Is the element an input? Should we search inside for any input?
this . input = this . element . is ( 'input' ) ? this . element : ( this . options . input ?
this . element . find ( this . options . input ) : false ) ;
if ( this . input && ( this . input . length === 0 ) ) {
this . input = false ;
}
// Set HSB color
this . color = this . createColor ( this . options . color !== false ? this . options . color : this . getValue ( ) ) ;
this . format = this . options . format !== false ? this . options . format : this . color . origFormat ;
if ( this . options . color !== false ) {
this . updateInput ( this . color ) ;
this . updateData ( this . color ) ;
}
this . disabled = false ;
// Setup picker
var $picker = this . picker = $ ( this . options . template ) ;
if ( this . options . customClass ) {
$picker . addClass ( this . options . customClass ) ;
}
if ( this . options . inline ) {
$picker . addClass ( 'colorpicker-inline colorpicker-visible' ) ;
} else {
$picker . addClass ( 'colorpicker-hidden' ) ;
}
if ( this . options . horizontal ) {
$picker . addClass ( 'colorpicker-horizontal' ) ;
}
if (
( [ 'rgba' , 'hsla' , 'alias' ] . indexOf ( this . format ) !== - 1 ) ||
this . options . format === false ||
this . getValue ( ) === 'transparent'
) {
$picker . addClass ( 'colorpicker-with-alpha' ) ;
}
if ( this . options . align === 'right' ) {
$picker . addClass ( 'colorpicker-right' ) ;
}
if ( this . options . inline === true ) {
$picker . addClass ( 'colorpicker-no-arrow' ) ;
}
if ( this . options . colorSelectors ) {
var colorpicker = this ,
selectorsContainer = colorpicker . picker . find ( '.colorpicker-selectors' ) ;
if ( selectorsContainer . length > 0 ) {
$ . each ( this . options . colorSelectors , function ( name , color ) {
var $btn = $ ( '<i />' )
. addClass ( 'colorpicker-selectors-color' )
. css ( 'background-color' , color )
. data ( 'class' , name ) . data ( 'alias' , name ) ;
$btn . on ( 'mousedown.colorpicker touchstart.colorpicker' , function ( event ) {
event . preventDefault ( ) ;
colorpicker . setValue (
colorpicker . format === 'alias' ? $ ( this ) . data ( 'alias' ) : $ ( this ) . css ( 'background-color' )
) ;
} ) ;
selectorsContainer . append ( $btn ) ;
} ) ;
selectorsContainer . show ( ) . addClass ( 'colorpicker-visible' ) ;
}
}
// Prevent closing the colorpicker when clicking on itself
$picker . on ( 'mousedown.colorpicker touchstart.colorpicker' , $ . proxy ( function ( e ) {
if ( e . target === e . currentTarget ) {
e . preventDefault ( ) ;
}
} , this ) ) ;
// Bind click/tap events on the sliders
$picker . find ( '.colorpicker-saturation, .colorpicker-hue, .colorpicker-alpha' )
. on ( 'mousedown.colorpicker touchstart.colorpicker' , $ . proxy ( this . mousedown , this ) ) ;
$picker . appendTo ( this . container ? this . container : $ ( 'body' ) ) ;
// Bind other events
if ( this . input !== false ) {
this . input . on ( {
'keyup.colorpicker' : $ . proxy ( this . keyup , this )
} ) ;
this . input . on ( {
'change.colorpicker' : $ . proxy ( this . change , this )
} ) ;
if ( this . component === false ) {
this . element . on ( {
'focus.colorpicker' : $ . proxy ( this . show , this )
} ) ;
}
if ( this . options . inline === false ) {
this . element . on ( {
'focusout.colorpicker' : $ . proxy ( this . hide , this )
} ) ;
}
}
if ( this . component !== false ) {
this . component . on ( {
'click.colorpicker' : $ . proxy ( this . show , this )
} ) ;
}
if ( ( this . input === false ) && ( this . component === false ) ) {
this . element . on ( {
'click.colorpicker' : $ . proxy ( this . show , this )
} ) ;
}
// for HTML5 input[type='color']
if ( ( this . input !== false ) && ( this . component !== false ) && ( this . input . attr ( 'type' ) === 'color' ) ) {
this . input . on ( {
'click.colorpicker' : $ . proxy ( this . show , this ) ,
'focus.colorpicker' : $ . proxy ( this . show , this )
} ) ;
}
this . update ( ) ;
$ ( $ . proxy ( function ( ) {
this . element . trigger ( 'create' ) ;
} , this ) ) ;
} ;
Colorpicker . Color = Color ;
Colorpicker . prototype = {
constructor : Colorpicker ,
destroy : function ( ) {
this . picker . remove ( ) ;
this . element . removeData ( 'colorpicker' , 'color' ) . off ( '.colorpicker' ) ;
if ( this . input !== false ) {
this . input . off ( '.colorpicker' ) ;
}
if ( this . component !== false ) {
this . component . off ( '.colorpicker' ) ;
}
this . element . removeClass ( 'colorpicker-element' ) ;
this . element . trigger ( {
type : 'destroy'
} ) ;
} ,
reposition : function ( ) {
if ( this . options . inline !== false || this . options . container ) {
return false ;
}
var type = this . container && this . container [ 0 ] !== window . document . body ? 'position' : 'offset' ;
var element = this . component || this . element ;
var offset = element [ type ] ( ) ;
if ( this . options . align === 'right' ) {
offset . left -= this . picker . outerWidth ( ) - element . outerWidth ( ) ;
}
this . picker . css ( {
top : offset . top + element . outerHeight ( ) ,
left : offset . left
} ) ;
} ,
show : function ( e ) {
if ( this . isDisabled ( ) ) {
// Don't show the widget if it's disabled (the input)
return ;
}
this . picker . addClass ( 'colorpicker-visible' ) . removeClass ( 'colorpicker-hidden' ) ;
this . reposition ( ) ;
$ ( window ) . on ( 'resize.colorpicker' , $ . proxy ( this . reposition , this ) ) ;
if ( e && ( ! this . hasInput ( ) || this . input . attr ( 'type' ) === 'color' ) ) {
if ( e . stopPropagation && e . preventDefault ) {
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
}
}
if ( ( this . component || ! this . input ) && ( this . options . inline === false ) ) {
$ ( window . document ) . on ( {
'mousedown.colorpicker' : $ . proxy ( this . hide , this )
} ) ;
}
this . element . trigger ( {
type : 'showPicker' ,
color : this . color
} ) ;
} ,
hide : function ( e ) {
if ( ( typeof e !== 'undefined' ) && e . target ) {
// Prevent hide if triggered by an event and an element inside the colorpicker has been clicked/touched
if (
$ ( e . currentTarget ) . parents ( '.colorpicker' ) . length > 0 ||
$ ( e . target ) . parents ( '.colorpicker' ) . length > 0
) {
return false ;
}
}
this . picker . addClass ( 'colorpicker-hidden' ) . removeClass ( 'colorpicker-visible' ) ;
$ ( window ) . off ( 'resize.colorpicker' , this . reposition ) ;
$ ( window . document ) . off ( {
'mousedown.colorpicker' : this . hide
} ) ;
this . update ( ) ;
this . element . trigger ( {
type : 'hidePicker' ,
color : this . color
} ) ;
} ,
updateData : function ( val ) {
val = val || this . color . toString ( false , this . format ) ;
this . element . data ( 'color' , val ) ;
return val ;
} ,
updateInput : function ( val ) {
val = val || this . color . toString ( false , this . format ) ;
if ( this . input !== false ) {
this . input . prop ( 'value' , val ) ;
this . input . trigger ( 'change' ) ;
}
return val ;
} ,
updatePicker : function ( val ) {
if ( typeof val !== 'undefined' ) {
this . color = this . createColor ( val ) ;
}
var sl = ( this . options . horizontal === false ) ? this . options . sliders : this . options . slidersHorz ;
var icns = this . picker . find ( 'i' ) ;
if ( icns . length === 0 ) {
return ;
}
if ( this . options . horizontal === false ) {
sl = this . options . sliders ;
icns . eq ( 1 ) . css ( 'top' , sl . hue . maxTop * ( 1 - this . color . value . h ) ) . end ( )
. eq ( 2 ) . css ( 'top' , sl . alpha . maxTop * ( 1 - this . color . value . a ) ) ;
} else {
sl = this . options . slidersHorz ;
icns . eq ( 1 ) . css ( 'left' , sl . hue . maxLeft * ( 1 - this . color . value . h ) ) . end ( )
. eq ( 2 ) . css ( 'left' , sl . alpha . maxLeft * ( 1 - this . color . value . a ) ) ;
}
icns . eq ( 0 ) . css ( {
'top' : sl . saturation . maxTop - this . color . value . b * sl . saturation . maxTop ,
'left' : this . color . value . s * sl . saturation . maxLeft
} ) ;
this . picker . find ( '.colorpicker-saturation' )
. css ( 'backgroundColor' , this . color . toHex ( true , this . color . value . h , 1 , 1 , 1 ) ) ;
this . picker . find ( '.colorpicker-alpha' )
. css ( 'backgroundColor' , this . color . toHex ( true ) ) ;
this . picker . find ( '.colorpicker-color, .colorpicker-color div' )
. css ( 'backgroundColor' , this . color . toString ( true , this . format ) ) ;
return val ;
} ,
updateComponent : function ( val ) {
var color ;
if ( typeof val !== 'undefined' ) {
color = this . createColor ( val ) ;
} else {
color = this . color ;
}
if ( this . component !== false ) {
var icn = this . component . find ( 'i' ) . eq ( 0 ) ;
if ( icn . length > 0 ) {
icn . css ( {
'backgroundColor' : color . toString ( true , this . format )
} ) ;
} else {
this . component . css ( {
'backgroundColor' : color . toString ( true , this . format )
} ) ;
}
}
return color . toString ( false , this . format ) ;
} ,
update : function ( force ) {
var val ;
if ( ( this . getValue ( false ) !== false ) || ( force === true ) ) {
// Update input/data only if the current value is not empty
val = this . updateComponent ( ) ;
this . updateInput ( val ) ;
this . updateData ( val ) ;
this . updatePicker ( ) ; // only update picker if value is not empty
}
return val ;
} ,
setValue : function ( val ) { // set color manually
this . color = this . createColor ( val ) ;
this . update ( true ) ;
this . element . trigger ( {
type : 'changeColor' ,
color : this . color ,
value : val
} ) ;
} ,
/ * *
* Creates a new color using the instance options
* @ protected
* @ param { String } val
* @ returns { Color }
* /
createColor : function ( val ) {
return new Color (
val ? val : null ,
this . options . colorSelectors ,
this . options . fallbackColor ? this . options . fallbackColor : this . color ,
this . options . fallbackFormat ,
this . options . hexNumberSignPrefix
) ;
} ,
getValue : function ( defaultValue ) {
defaultValue = ( typeof defaultValue === 'undefined' ) ? this . options . fallbackColor : defaultValue ;
var val ;
if ( this . hasInput ( ) ) {
val = this . input . val ( ) ;
} else {
val = this . element . data ( 'color' ) ;
}
if ( ( val === undefined ) || ( val === '' ) || ( val === null ) ) {
// if not defined or empty, return default
val = defaultValue ;
}
return val ;
} ,
hasInput : function ( ) {
return ( this . input !== false ) ;
} ,
isDisabled : function ( ) {
return this . disabled ;
} ,
disable : function ( ) {
if ( this . hasInput ( ) ) {
this . input . prop ( 'disabled' , true ) ;
}
this . disabled = true ;
this . element . trigger ( {
type : 'disable' ,
color : this . color ,
value : this . getValue ( )
} ) ;
return true ;
} ,
enable : function ( ) {
if ( this . hasInput ( ) ) {
this . input . prop ( 'disabled' , false ) ;
}
this . disabled = false ;
this . element . trigger ( {
type : 'enable' ,
color : this . color ,
value : this . getValue ( )
} ) ;
return true ;
} ,
currentSlider : null ,
mousePointer : {
left : 0 ,
top : 0
} ,
mousedown : function ( e ) {
if ( ! e . pageX && ! e . pageY && e . originalEvent && e . originalEvent . touches ) {
e . pageX = e . originalEvent . touches [ 0 ] . pageX ;
e . pageY = e . originalEvent . touches [ 0 ] . pageY ;
}
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
var target = $ ( e . target ) ;
//detect the slider and set the limits and callbacks
var zone = target . closest ( 'div' ) ;
var sl = this . options . horizontal ? this . options . slidersHorz : this . options . sliders ;
if ( ! zone . is ( '.colorpicker' ) ) {
if ( zone . is ( '.colorpicker-saturation' ) ) {
this . currentSlider = $ . extend ( { } , sl . saturation ) ;
} else if ( zone . is ( '.colorpicker-hue' ) ) {
this . currentSlider = $ . extend ( { } , sl . hue ) ;
} else if ( zone . is ( '.colorpicker-alpha' ) ) {
this . currentSlider = $ . extend ( { } , sl . alpha ) ;
} else {
return false ;
}
var offset = zone . offset ( ) ;
//reference to guide's style
this . currentSlider . guide = zone . find ( 'i' ) [ 0 ] . style ;
this . currentSlider . left = e . pageX - offset . left ;
this . currentSlider . top = e . pageY - offset . top ;
this . mousePointer = {
left : e . pageX ,
top : e . pageY
} ;
//trigger mousemove to move the guide to the current position
$ ( window . document ) . on ( {
'mousemove.colorpicker' : $ . proxy ( this . mousemove , this ) ,
'touchmove.colorpicker' : $ . proxy ( this . mousemove , this ) ,
'mouseup.colorpicker' : $ . proxy ( this . mouseup , this ) ,
'touchend.colorpicker' : $ . proxy ( this . mouseup , this )
} ) . trigger ( 'mousemove' ) ;
}
return false ;
} ,
mousemove : function ( e ) {
if ( ! e . pageX && ! e . pageY && e . originalEvent && e . originalEvent . touches ) {
e . pageX = e . originalEvent . touches [ 0 ] . pageX ;
e . pageY = e . originalEvent . touches [ 0 ] . pageY ;
}
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
var left = Math . max (
0 ,
Math . min (
this . currentSlider . maxLeft ,
this . currentSlider . left + ( ( e . pageX || this . mousePointer . left ) - this . mousePointer . left )
)
) ;
var top = Math . max (
0 ,
Math . min (
this . currentSlider . maxTop ,
this . currentSlider . top + ( ( e . pageY || this . mousePointer . top ) - this . mousePointer . top )
)
) ;
this . currentSlider . guide . left = left + 'px' ;
this . currentSlider . guide . top = top + 'px' ;
if ( this . currentSlider . callLeft ) {
this . color [ this . currentSlider . callLeft ] . call ( this . color , left / this . currentSlider . maxLeft ) ;
}
if ( this . currentSlider . callTop ) {
this . color [ this . currentSlider . callTop ] . call ( this . color , top / this . currentSlider . maxTop ) ;
}
// Change format dynamically
// Only occurs if user choose the dynamic format by
// setting option format to false
if (
this . options . format === false &&
( this . currentSlider . callTop === 'setAlpha' ||
this . currentSlider . callLeft === 'setAlpha' )
) {
// Converting from hex / rgb to rgba
if ( this . color . value . a !== 1 ) {
this . format = 'rgba' ;
this . color . origFormat = 'rgba' ;
}
// Converting from rgba to hex
else {
this . format = 'hex' ;
this . color . origFormat = 'hex' ;
}
}
this . update ( true ) ;
this . element . trigger ( {
type : 'changeColor' ,
color : this . color
} ) ;
return false ;
} ,
mouseup : function ( e ) {
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
$ ( window . document ) . off ( {
'mousemove.colorpicker' : this . mousemove ,
'touchmove.colorpicker' : this . mousemove ,
'mouseup.colorpicker' : this . mouseup ,
'touchend.colorpicker' : this . mouseup
} ) ;
return false ;
} ,
change : function ( e ) {
this . keyup ( e ) ;
} ,
keyup : function ( e ) {
if ( ( e . keyCode === 38 ) ) {
if ( this . color . value . a < 1 ) {
this . color . value . a = Math . round ( ( this . color . value . a + 0.01 ) * 100 ) / 100 ;
}
this . update ( true ) ;
} else if ( ( e . keyCode === 40 ) ) {
if ( this . color . value . a > 0 ) {
this . color . value . a = Math . round ( ( this . color . value . a - 0.01 ) * 100 ) / 100 ;
}
this . update ( true ) ;
} else {
this . color = this . createColor ( this . input . val ( ) ) ;
// Change format dynamically
// Only occurs if user choose the dynamic format by
// setting option format to false
if ( this . color . origFormat && this . options . format === false ) {
this . format = this . color . origFormat ;
}
if ( this . getValue ( false ) !== false ) {
this . updateData ( ) ;
this . updateComponent ( ) ;
this . updatePicker ( ) ;
}
}
this . element . trigger ( {
type : 'changeColor' ,
color : this . color ,
value : this . input . val ( )
} ) ;
}
} ;
$ . colorpicker = Colorpicker ;
$ . fn . colorpicker = function ( option ) {
var apiArgs = Array . prototype . slice . call ( arguments , 1 ) ,
isSingleElement = ( this . length === 1 ) ,
returnValue = null ;
var $jq = this . each ( function ( ) {
var $this = $ ( this ) ,
inst = $this . data ( 'colorpicker' ) ,
options = ( ( typeof option === 'object' ) ? option : { } ) ;
if ( ! inst ) {
inst = new Colorpicker ( this , options ) ;
$this . data ( 'colorpicker' , inst ) ;
}
if ( typeof option === 'string' ) {
if ( $ . isFunction ( inst [ option ] ) ) {
returnValue = inst [ option ] . apply ( inst , apiArgs ) ;
} else { // its a property ?
if ( apiArgs . length ) {
// set property
inst [ option ] = apiArgs [ 0 ] ;
}
returnValue = inst [ option ] ;
}
} else {
returnValue = $this ;
}
} ) ;
return isSingleElement ? returnValue : $jq ;
} ;
$ . fn . colorpicker . constructor = Colorpicker ;
} ) ) ;
/ * !
* Datepicker for Bootstrap v1 . 7.1 ( https : //github.com/uxsolutions/bootstrap-datepicker)
*
* Licensed under the Apache License v2 . 0 ( http : //www.apache.org/licenses/LICENSE-2.0)
* /
( function ( factory ) {
if ( typeof define === "function" && define . amd ) {
define ( [ "jquery" ] , factory ) ;
} else if ( typeof exports === 'object' ) {
factory ( require ( 'jquery' ) ) ;
} else {
factory ( jQuery ) ;
}
} ( function ( $ , undefined ) {
function UTCDate ( ) {
return new Date ( Date . UTC . apply ( Date , arguments ) ) ;
}
function UTCToday ( ) {
var today = new Date ( ) ;
return UTCDate ( today . getFullYear ( ) , today . getMonth ( ) , today . getDate ( ) ) ;
}
function isUTCEquals ( date1 , date2 ) {
return (
date1 . getUTCFullYear ( ) === date2 . getUTCFullYear ( ) &&
date1 . getUTCMonth ( ) === date2 . getUTCMonth ( ) &&
date1 . getUTCDate ( ) === date2 . getUTCDate ( )
) ;
}
function alias ( method , deprecationMsg ) {
return function ( ) {
if ( deprecationMsg !== undefined ) {
$ . fn . datepicker . deprecated ( deprecationMsg ) ;
}
return this [ method ] . apply ( this , arguments ) ;
} ;
}
function isValidDate ( d ) {
return d && ! isNaN ( d . getTime ( ) ) ;
}
var DateArray = ( function ( ) {
var extras = {
get : function ( i ) {
return this . slice ( i ) [ 0 ] ;
} ,
contains : function ( d ) {
// Array.indexOf is not cross-browser;
// $.inArray doesn't work with Dates
var val = d && d . valueOf ( ) ;
for ( var i = 0 , l = this . length ; i < l ; i ++ )
// Use date arithmetic to allow dates with different times to match
if ( 0 <= this [ i ] . valueOf ( ) - val && this [ i ] . valueOf ( ) - val < 1000 * 60 * 60 * 24 )
return i ;
return - 1 ;
} ,
remove : function ( i ) {
this . splice ( i , 1 ) ;
} ,
replace : function ( new _array ) {
if ( ! new _array )
return ;
if ( ! $ . isArray ( new _array ) )
new _array = [ new _array ] ;
this . clear ( ) ;
this . push . apply ( this , new _array ) ;
} ,
clear : function ( ) {
this . length = 0 ;
} ,
copy : function ( ) {
var a = new DateArray ( ) ;
a . replace ( this ) ;
return a ;
}
} ;
return function ( ) {
var a = [ ] ;
a . push . apply ( a , arguments ) ;
$ . extend ( a , extras ) ;
return a ;
} ;
} ) ( ) ;
// Picker object
var Datepicker = function ( element , options ) {
$ . data ( element , 'datepicker' , this ) ;
this . _process _options ( options ) ;
this . dates = new DateArray ( ) ;
this . viewDate = this . o . defaultViewDate ;
this . focusDate = null ;
this . element = $ ( element ) ;
this . isInput = this . element . is ( 'input' ) ;
this . inputField = this . isInput ? this . element : this . element . find ( 'input' ) ;
this . component = this . element . hasClass ( 'date' ) ? this . element . find ( '.add-on, .input-group-addon, .btn' ) : false ;
if ( this . component && this . component . length === 0 )
this . component = false ;
this . isInline = ! this . component && this . element . is ( 'div' ) ;
this . picker = $ ( DPGlobal . template ) ;
// Checking templates and inserting
if ( this . _check _template ( this . o . templates . leftArrow ) ) {
this . picker . find ( '.prev' ) . html ( this . o . templates . leftArrow ) ;
}
if ( this . _check _template ( this . o . templates . rightArrow ) ) {
this . picker . find ( '.next' ) . html ( this . o . templates . rightArrow ) ;
}
this . _buildEvents ( ) ;
this . _attachEvents ( ) ;
if ( this . isInline ) {
this . picker . addClass ( 'datepicker-inline' ) . appendTo ( this . element ) ;
}
else {
this . picker . addClass ( 'datepicker-dropdown dropdown-menu' ) ;
}
if ( this . o . rtl ) {
this . picker . addClass ( 'datepicker-rtl' ) ;
}
if ( this . o . calendarWeeks ) {
this . picker . find ( '.datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear' )
. attr ( 'colspan' , function ( i , val ) {
return Number ( val ) + 1 ;
} ) ;
}
this . _process _options ( {
startDate : this . _o . startDate ,
endDate : this . _o . endDate ,
daysOfWeekDisabled : this . o . daysOfWeekDisabled ,
daysOfWeekHighlighted : this . o . daysOfWeekHighlighted ,
datesDisabled : this . o . datesDisabled
} ) ;
this . _allow _update = false ;
this . setViewMode ( this . o . startView ) ;
this . _allow _update = true ;
this . fillDow ( ) ;
this . fillMonths ( ) ;
this . update ( ) ;
if ( this . isInline ) {
this . show ( ) ;
}
} ;
Datepicker . prototype = {
constructor : Datepicker ,
_resolveViewName : function ( view ) {
$ . each ( DPGlobal . viewModes , function ( i , viewMode ) {
if ( view === i || $ . inArray ( view , viewMode . names ) !== - 1 ) {
view = i ;
return false ;
}
} ) ;
return view ;
} ,
_resolveDaysOfWeek : function ( daysOfWeek ) {
if ( ! $ . isArray ( daysOfWeek ) )
daysOfWeek = daysOfWeek . split ( /[,\s]*/ ) ;
return $ . map ( daysOfWeek , Number ) ;
} ,
_check _template : function ( tmp ) {
try {
// If empty
if ( tmp === undefined || tmp === "" ) {
return false ;
}
// If no html, everything ok
if ( ( tmp . match ( /[<>]/g ) || [ ] ) . length <= 0 ) {
return true ;
}
// Checking if html is fine
var jDom = $ ( tmp ) ;
return jDom . length > 0 ;
}
catch ( ex ) {
return false ;
}
} ,
_process _options : function ( opts ) {
// Store raw options for reference
this . _o = $ . extend ( { } , this . _o , opts ) ;
// Processed options
var o = this . o = $ . extend ( { } , this . _o ) ;
// Check if "de-DE" style date is available, if not language should
// fallback to 2 letter code eg "de"
var lang = o . language ;
if ( ! dates [ lang ] ) {
lang = lang . split ( '-' ) [ 0 ] ;
if ( ! dates [ lang ] )
lang = defaults . language ;
}
o . language = lang ;
// Retrieve view index from any aliases
o . startView = this . _resolveViewName ( o . startView ) ;
o . minViewMode = this . _resolveViewName ( o . minViewMode ) ;
o . maxViewMode = this . _resolveViewName ( o . maxViewMode ) ;
// Check view is between min and max
o . startView = Math . max ( this . o . minViewMode , Math . min ( this . o . maxViewMode , o . startView ) ) ;
// true, false, or Number > 0
if ( o . multidate !== true ) {
o . multidate = Number ( o . multidate ) || false ;
if ( o . multidate !== false )
o . multidate = Math . max ( 0 , o . multidate ) ;
}
o . multidateSeparator = String ( o . multidateSeparator ) ;
o . weekStart %= 7 ;
o . weekEnd = ( o . weekStart + 6 ) % 7 ;
var format = DPGlobal . parseFormat ( o . format ) ;
if ( o . startDate !== - Infinity ) {
if ( ! ! o . startDate ) {
if ( o . startDate instanceof Date )
o . startDate = this . _local _to _utc ( this . _zero _time ( o . startDate ) ) ;
else
o . startDate = DPGlobal . parseDate ( o . startDate , format , o . language , o . assumeNearbyYear ) ;
}
else {
o . startDate = - Infinity ;
}
}
if ( o . endDate !== Infinity ) {
if ( ! ! o . endDate ) {
if ( o . endDate instanceof Date )
o . endDate = this . _local _to _utc ( this . _zero _time ( o . endDate ) ) ;
else
o . endDate = DPGlobal . parseDate ( o . endDate , format , o . language , o . assumeNearbyYear ) ;
}
else {
o . endDate = Infinity ;
}
}
o . daysOfWeekDisabled = this . _resolveDaysOfWeek ( o . daysOfWeekDisabled || [ ] ) ;
o . daysOfWeekHighlighted = this . _resolveDaysOfWeek ( o . daysOfWeekHighlighted || [ ] ) ;
o . datesDisabled = o . datesDisabled || [ ] ;
if ( ! $ . isArray ( o . datesDisabled ) ) {
o . datesDisabled = o . datesDisabled . split ( ',' ) ;
}
o . datesDisabled = $ . map ( o . datesDisabled , function ( d ) {
return DPGlobal . parseDate ( d , format , o . language , o . assumeNearbyYear ) ;
} ) ;
var plc = String ( o . orientation ) . toLowerCase ( ) . split ( /\s+/g ) ,
_plc = o . orientation . toLowerCase ( ) ;
plc = $ . grep ( plc , function ( word ) {
return /^auto|left|right|top|bottom$/ . test ( word ) ;
} ) ;
o . orientation = { x : 'auto' , y : 'auto' } ;
if ( ! _plc || _plc === 'auto' )
; // no action
else if ( plc . length === 1 ) {
switch ( plc [ 0 ] ) {
case 'top' :
case 'bottom' :
o . orientation . y = plc [ 0 ] ;
break ;
case 'left' :
case 'right' :
o . orientation . x = plc [ 0 ] ;
break ;
}
}
else {
_plc = $ . grep ( plc , function ( word ) {
return /^left|right$/ . test ( word ) ;
} ) ;
o . orientation . x = _plc [ 0 ] || 'auto' ;
_plc = $ . grep ( plc , function ( word ) {
return /^top|bottom$/ . test ( word ) ;
} ) ;
o . orientation . y = _plc [ 0 ] || 'auto' ;
}
if ( o . defaultViewDate instanceof Date || typeof o . defaultViewDate === 'string' ) {
o . defaultViewDate = DPGlobal . parseDate ( o . defaultViewDate , format , o . language , o . assumeNearbyYear ) ;
} else if ( o . defaultViewDate ) {
var year = o . defaultViewDate . year || new Date ( ) . getFullYear ( ) ;
var month = o . defaultViewDate . month || 0 ;
var day = o . defaultViewDate . day || 1 ;
o . defaultViewDate = UTCDate ( year , month , day ) ;
} else {
o . defaultViewDate = UTCToday ( ) ;
}
} ,
_events : [ ] ,
_secondaryEvents : [ ] ,
_applyEvents : function ( evs ) {
for ( var i = 0 , el , ch , ev ; i < evs . length ; i ++ ) {
el = evs [ i ] [ 0 ] ;
if ( evs [ i ] . length === 2 ) {
ch = undefined ;
ev = evs [ i ] [ 1 ] ;
} else if ( evs [ i ] . length === 3 ) {
ch = evs [ i ] [ 1 ] ;
ev = evs [ i ] [ 2 ] ;
}
el . on ( ev , ch ) ;
}
} ,
_unapplyEvents : function ( evs ) {
for ( var i = 0 , el , ev , ch ; i < evs . length ; i ++ ) {
el = evs [ i ] [ 0 ] ;
if ( evs [ i ] . length === 2 ) {
ch = undefined ;
ev = evs [ i ] [ 1 ] ;
} else if ( evs [ i ] . length === 3 ) {
ch = evs [ i ] [ 1 ] ;
ev = evs [ i ] [ 2 ] ;
}
el . off ( ev , ch ) ;
}
} ,
_buildEvents : function ( ) {
var events = {
keyup : $ . proxy ( function ( e ) {
if ( $ . inArray ( e . keyCode , [ 27 , 37 , 39 , 38 , 40 , 32 , 13 , 9 ] ) === - 1 )
this . update ( ) ;
} , this ) ,
keydown : $ . proxy ( this . keydown , this ) ,
paste : $ . proxy ( this . paste , this )
} ;
if ( this . o . showOnFocus === true ) {
events . focus = $ . proxy ( this . show , this ) ;
}
if ( this . isInput ) { // single input
this . _events = [
[ this . element , events ]
] ;
}
// component: input + button
else if ( this . component && this . inputField . length ) {
this . _events = [
// For components that are not readonly, allow keyboard nav
[ this . inputField , events ] ,
[ this . component , {
click : $ . proxy ( this . show , this )
} ]
] ;
}
else {
this . _events = [
[ this . element , {
click : $ . proxy ( this . show , this ) ,
keydown : $ . proxy ( this . keydown , this )
} ]
] ;
}
this . _events . push (
// Component: listen for blur on element descendants
[ this . element , '*' , {
blur : $ . proxy ( function ( e ) {
this . _focused _from = e . target ;
} , this )
} ] ,
// Input: listen for blur on element
[ this . element , {
blur : $ . proxy ( function ( e ) {
this . _focused _from = e . target ;
} , this )
} ]
) ;
if ( this . o . immediateUpdates ) {
// Trigger input updates immediately on changed year/month
this . _events . push ( [ this . element , {
'changeYear changeMonth' : $ . proxy ( function ( e ) {
this . update ( e . date ) ;
} , this )
} ] ) ;
}
this . _secondaryEvents = [
[ this . picker , {
click : $ . proxy ( this . click , this )
} ] ,
[ this . picker , '.prev, .next' , {
click : $ . proxy ( this . navArrowsClick , this )
} ] ,
[ this . picker , '.day:not(.disabled)' , {
click : $ . proxy ( this . dayCellClick , this )
} ] ,
[ $ ( window ) , {
resize : $ . proxy ( this . place , this )
} ] ,
[ $ ( document ) , {
'mousedown touchstart' : $ . proxy ( function ( e ) {
// Clicked outside the datepicker, hide it
if ( ! (
this . element . is ( e . target ) ||
this . element . find ( e . target ) . length ||
this . picker . is ( e . target ) ||
this . picker . find ( e . target ) . length ||
this . isInline
) ) {
this . hide ( ) ;
}
} , this )
} ]
] ;
} ,
_attachEvents : function ( ) {
this . _detachEvents ( ) ;
this . _applyEvents ( this . _events ) ;
} ,
_detachEvents : function ( ) {
this . _unapplyEvents ( this . _events ) ;
} ,
_attachSecondaryEvents : function ( ) {
this . _detachSecondaryEvents ( ) ;
this . _applyEvents ( this . _secondaryEvents ) ;
} ,
_detachSecondaryEvents : function ( ) {
this . _unapplyEvents ( this . _secondaryEvents ) ;
} ,
_trigger : function ( event , altdate ) {
var date = altdate || this . dates . get ( - 1 ) ,
local _date = this . _utc _to _local ( date ) ;
this . element . trigger ( {
type : event ,
date : local _date ,
viewMode : this . viewMode ,
dates : $ . map ( this . dates , this . _utc _to _local ) ,
format : $ . proxy ( function ( ix , format ) {
if ( arguments . length === 0 ) {
ix = this . dates . length - 1 ;
format = this . o . format ;
} else if ( typeof ix === 'string' ) {
format = ix ;
ix = this . dates . length - 1 ;
}
format = format || this . o . format ;
var date = this . dates . get ( ix ) ;
return DPGlobal . formatDate ( date , format , this . o . language ) ;
} , this )
} ) ;
} ,
show : function ( ) {
if ( this . inputField . prop ( 'disabled' ) || ( this . inputField . prop ( 'readonly' ) && this . o . enableOnReadonly === false ) )
return ;
if ( ! this . isInline )
this . picker . appendTo ( this . o . container ) ;
this . place ( ) ;
this . picker . show ( ) ;
this . _attachSecondaryEvents ( ) ;
this . _trigger ( 'show' ) ;
if ( ( window . navigator . msMaxTouchPoints || 'ontouchstart' in document ) && this . o . disableTouchKeyboard ) {
$ ( this . element ) . blur ( ) ;
}
return this ;
} ,
hide : function ( ) {
if ( this . isInline || ! this . picker . is ( ':visible' ) )
return this ;
this . focusDate = null ;
this . picker . hide ( ) . detach ( ) ;
this . _detachSecondaryEvents ( ) ;
this . setViewMode ( this . o . startView ) ;
if ( this . o . forceParse && this . inputField . val ( ) )
this . setValue ( ) ;
this . _trigger ( 'hide' ) ;
return this ;
} ,
destroy : function ( ) {
this . hide ( ) ;
this . _detachEvents ( ) ;
this . _detachSecondaryEvents ( ) ;
this . picker . remove ( ) ;
delete this . element . data ( ) . datepicker ;
if ( ! this . isInput ) {
delete this . element . data ( ) . date ;
}
return this ;
} ,
paste : function ( e ) {
var dateString ;
if ( e . originalEvent . clipboardData && e . originalEvent . clipboardData . types
&& $ . inArray ( 'text/plain' , e . originalEvent . clipboardData . types ) !== - 1 ) {
dateString = e . originalEvent . clipboardData . getData ( 'text/plain' ) ;
} else if ( window . clipboardData ) {
dateString = window . clipboardData . getData ( 'Text' ) ;
} else {
return ;
}
this . setDate ( dateString ) ;
this . update ( ) ;
e . preventDefault ( ) ;
} ,
_utc _to _local : function ( utc ) {
if ( ! utc ) {
return utc ;
}
var local = new Date ( utc . getTime ( ) + ( utc . getTimezoneOffset ( ) * 60000 ) ) ;
if ( local . getTimezoneOffset ( ) !== utc . getTimezoneOffset ( ) ) {
local = new Date ( utc . getTime ( ) + ( local . getTimezoneOffset ( ) * 60000 ) ) ;
}
return local ;
} ,
_local _to _utc : function ( local ) {
return local && new Date ( local . getTime ( ) - ( local . getTimezoneOffset ( ) * 60000 ) ) ;
} ,
_zero _time : function ( local ) {
return local && new Date ( local . getFullYear ( ) , local . getMonth ( ) , local . getDate ( ) ) ;
} ,
_zero _utc _time : function ( utc ) {
return utc && UTCDate ( utc . getUTCFullYear ( ) , utc . getUTCMonth ( ) , utc . getUTCDate ( ) ) ;
} ,
getDates : function ( ) {
return $ . map ( this . dates , this . _utc _to _local ) ;
} ,
getUTCDates : function ( ) {
return $ . map ( this . dates , function ( d ) {
return new Date ( d ) ;
} ) ;
} ,
getDate : function ( ) {
return this . _utc _to _local ( this . getUTCDate ( ) ) ;
} ,
getUTCDate : function ( ) {
var selected _date = this . dates . get ( - 1 ) ;
if ( selected _date !== undefined ) {
return new Date ( selected _date ) ;
} else {
return null ;
}
} ,
clearDates : function ( ) {
this . inputField . val ( '' ) ;
this . update ( ) ;
this . _trigger ( 'changeDate' ) ;
if ( this . o . autoclose ) {
this . hide ( ) ;
}
} ,
setDates : function ( ) {
var args = $ . isArray ( arguments [ 0 ] ) ? arguments [ 0 ] : arguments ;
this . update . apply ( this , args ) ;
this . _trigger ( 'changeDate' ) ;
this . setValue ( ) ;
return this ;
} ,
setUTCDates : function ( ) {
var args = $ . isArray ( arguments [ 0 ] ) ? arguments [ 0 ] : arguments ;
this . setDates . apply ( this , $ . map ( args , this . _utc _to _local ) ) ;
return this ;
} ,
setDate : alias ( 'setDates' ) ,
setUTCDate : alias ( 'setUTCDates' ) ,
remove : alias ( 'destroy' , 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead' ) ,
setValue : function ( ) {
var formatted = this . getFormattedDate ( ) ;
this . inputField . val ( formatted ) ;
return this ;
} ,
getFormattedDate : function ( format ) {
if ( format === undefined )
format = this . o . format ;
var lang = this . o . language ;
return $ . map ( this . dates , function ( d ) {
return DPGlobal . formatDate ( d , format , lang ) ;
} ) . join ( this . o . multidateSeparator ) ;
} ,
getStartDate : function ( ) {
return this . o . startDate ;
} ,
setStartDate : function ( startDate ) {
this . _process _options ( { startDate : startDate } ) ;
this . update ( ) ;
this . updateNavArrows ( ) ;
return this ;
} ,
getEndDate : function ( ) {
return this . o . endDate ;
} ,
setEndDate : function ( endDate ) {
this . _process _options ( { endDate : endDate } ) ;
this . update ( ) ;
this . updateNavArrows ( ) ;
return this ;
} ,
setDaysOfWeekDisabled : function ( daysOfWeekDisabled ) {
this . _process _options ( { daysOfWeekDisabled : daysOfWeekDisabled } ) ;
this . update ( ) ;
return this ;
} ,
setDaysOfWeekHighlighted : function ( daysOfWeekHighlighted ) {
this . _process _options ( { daysOfWeekHighlighted : daysOfWeekHighlighted } ) ;
this . update ( ) ;
return this ;
} ,
setDatesDisabled : function ( datesDisabled ) {
this . _process _options ( { datesDisabled : datesDisabled } ) ;
this . update ( ) ;
return this ;
} ,
place : function ( ) {
if ( this . isInline )
return this ;
var calendarWidth = this . picker . outerWidth ( ) ,
calendarHeight = this . picker . outerHeight ( ) ,
visualPadding = 10 ,
container = $ ( this . o . container ) ,
windowWidth = container . width ( ) ,
scrollTop = this . o . container === 'body' ? $ ( document ) . scrollTop ( ) : container . scrollTop ( ) ,
appendOffset = container . offset ( ) ;
var parentsZindex = [ 0 ] ;
this . element . parents ( ) . each ( function ( ) {
var itemZIndex = $ ( this ) . css ( 'z-index' ) ;
if ( itemZIndex !== 'auto' && Number ( itemZIndex ) !== 0 ) parentsZindex . push ( Number ( itemZIndex ) ) ;
} ) ;
var zIndex = Math . max . apply ( Math , parentsZindex ) + this . o . zIndexOffset ;
var offset = this . component ? this . component . parent ( ) . offset ( ) : this . element . offset ( ) ;
var height = this . component ? this . component . outerHeight ( true ) : this . element . outerHeight ( false ) ;
var width = this . component ? this . component . outerWidth ( true ) : this . element . outerWidth ( false ) ;
var left = offset . left - appendOffset . left ;
var top = offset . top - appendOffset . top ;
if ( this . o . container !== 'body' ) {
top += scrollTop ;
}
this . picker . removeClass (
'datepicker-orient-top datepicker-orient-bottom ' +
'datepicker-orient-right datepicker-orient-left'
) ;
if ( this . o . orientation . x !== 'auto' ) {
this . picker . addClass ( 'datepicker-orient-' + this . o . orientation . x ) ;
if ( this . o . orientation . x === 'right' )
left -= calendarWidth - width ;
}
// auto x orientation is best-placement: if it crosses a window
// edge, fudge it sideways
else {
if ( offset . left < 0 ) {
// component is outside the window on the left side. Move it into visible range
this . picker . addClass ( 'datepicker-orient-left' ) ;
left -= offset . left - visualPadding ;
} else if ( left + calendarWidth > windowWidth ) {
// the calendar passes the widow right edge. Align it to component right side
this . picker . addClass ( 'datepicker-orient-right' ) ;
left += width - calendarWidth ;
} else {
if ( this . o . rtl ) {
// Default to right
this . picker . addClass ( 'datepicker-orient-right' ) ;
} else {
// Default to left
this . picker . addClass ( 'datepicker-orient-left' ) ;
}
}
}
// auto y orientation is best-situation: top or bottom, no fudging,
// decision based on which shows more of the calendar
var yorient = this . o . orientation . y ,
top _overflow ;
if ( yorient === 'auto' ) {
top _overflow = - scrollTop + top - calendarHeight ;
yorient = top _overflow < 0 ? 'bottom' : 'top' ;
}
this . picker . addClass ( 'datepicker-orient-' + yorient ) ;
if ( yorient === 'top' )
top -= calendarHeight + parseInt ( this . picker . css ( 'padding-top' ) ) ;
else
top += height ;
if ( this . o . rtl ) {
var right = windowWidth - ( left + width ) ;
this . picker . css ( {
top : top ,
right : right ,
zIndex : zIndex
} ) ;
} else {
this . picker . css ( {
top : top ,
left : left ,
zIndex : zIndex
} ) ;
}
return this ;
} ,
_allow _update : true ,
update : function ( ) {
if ( ! this . _allow _update )
return this ;
var oldDates = this . dates . copy ( ) ,
dates = [ ] ,
fromArgs = false ;
if ( arguments . length ) {
$ . each ( arguments , $ . proxy ( function ( i , date ) {
if ( date instanceof Date )
date = this . _local _to _utc ( date ) ;
dates . push ( date ) ;
} , this ) ) ;
fromArgs = true ;
} else {
dates = this . isInput
? this . element . val ( )
: this . element . data ( 'date' ) || this . inputField . val ( ) ;
if ( dates && this . o . multidate )
dates = dates . split ( this . o . multidateSeparator ) ;
else
dates = [ dates ] ;
delete this . element . data ( ) . date ;
}
dates = $ . map ( dates , $ . proxy ( function ( date ) {
return DPGlobal . parseDate ( date , this . o . format , this . o . language , this . o . assumeNearbyYear ) ;
} , this ) ) ;
dates = $ . grep ( dates , $ . proxy ( function ( date ) {
return (
! this . dateWithinRange ( date ) ||
! date
) ;
} , this ) , true ) ;
this . dates . replace ( dates ) ;
if ( this . o . updateViewDate ) {
if ( this . dates . length )
this . viewDate = new Date ( this . dates . get ( - 1 ) ) ;
else if ( this . viewDate < this . o . startDate )
this . viewDate = new Date ( this . o . startDate ) ;
else if ( this . viewDate > this . o . endDate )
this . viewDate = new Date ( this . o . endDate ) ;
else
this . viewDate = this . o . defaultViewDate ;
}
if ( fromArgs ) {
// setting date by clicking
this . setValue ( ) ;
this . element . change ( ) ;
}
else if ( this . dates . length ) {
// setting date by typing
if ( String ( oldDates ) !== String ( this . dates ) && fromArgs ) {
this . _trigger ( 'changeDate' ) ;
this . element . change ( ) ;
}
}
if ( ! this . dates . length && oldDates . length ) {
this . _trigger ( 'clearDate' ) ;
this . element . change ( ) ;
}
this . fill ( ) ;
return this ;
} ,
fillDow : function ( ) {
if ( this . o . showWeekDays ) {
var dowCnt = this . o . weekStart ,
html = '<tr>' ;
if ( this . o . calendarWeeks ) {
html += '<th class="cw"> </th>' ;
}
while ( dowCnt < this . o . weekStart + 7 ) {
html += '<th class="dow' ;
if ( $ . inArray ( dowCnt , this . o . daysOfWeekDisabled ) !== - 1 )
html += ' disabled' ;
html += '">' + dates [ this . o . language ] . daysMin [ ( dowCnt ++ ) % 7 ] + '</th>' ;
}
html += '</tr>' ;
this . picker . find ( '.datepicker-days thead' ) . append ( html ) ;
}
} ,
fillMonths : function ( ) {
var localDate = this . _utc _to _local ( this . viewDate ) ;
var html = '' ;
var focused ;
for ( var i = 0 ; i < 12 ; i ++ ) {
focused = localDate && localDate . getMonth ( ) === i ? ' focused' : '' ;
html += '<span class="month' + focused + '">' + dates [ this . o . language ] . monthsShort [ i ] + '</span>' ;
}
this . picker . find ( '.datepicker-months td' ) . html ( html ) ;
} ,
setRange : function ( range ) {
if ( ! range || ! range . length )
delete this . range ;
else
this . range = $ . map ( range , function ( d ) {
return d . valueOf ( ) ;
} ) ;
this . fill ( ) ;
} ,
getClassNames : function ( date ) {
var cls = [ ] ,
year = this . viewDate . getUTCFullYear ( ) ,
month = this . viewDate . getUTCMonth ( ) ,
today = UTCToday ( ) ;
if ( date . getUTCFullYear ( ) < year || ( date . getUTCFullYear ( ) === year && date . getUTCMonth ( ) < month ) ) {
cls . push ( 'old' ) ;
} else if ( date . getUTCFullYear ( ) > year || ( date . getUTCFullYear ( ) === year && date . getUTCMonth ( ) > month ) ) {
cls . push ( 'new' ) ;
}
if ( this . focusDate && date . valueOf ( ) === this . focusDate . valueOf ( ) )
cls . push ( 'focused' ) ;
// Compare internal UTC date with UTC today, not local today
if ( this . o . todayHighlight && isUTCEquals ( date , today ) ) {
cls . push ( 'today' ) ;
}
if ( this . dates . contains ( date ) !== - 1 )
cls . push ( 'active' ) ;
if ( ! this . dateWithinRange ( date ) ) {
cls . push ( 'disabled' ) ;
}
if ( this . dateIsDisabled ( date ) ) {
cls . push ( 'disabled' , 'disabled-date' ) ;
}
if ( $ . inArray ( date . getUTCDay ( ) , this . o . daysOfWeekHighlighted ) !== - 1 ) {
cls . push ( 'highlighted' ) ;
}
if ( this . range ) {
if ( date > this . range [ 0 ] && date < this . range [ this . range . length - 1 ] ) {
cls . push ( 'range' ) ;
}
if ( $ . inArray ( date . valueOf ( ) , this . range ) !== - 1 ) {
cls . push ( 'selected' ) ;
}
if ( date . valueOf ( ) === this . range [ 0 ] ) {
cls . push ( 'range-start' ) ;
}
if ( date . valueOf ( ) === this . range [ this . range . length - 1 ] ) {
cls . push ( 'range-end' ) ;
}
}
return cls ;
} ,
_fill _yearsView : function ( selector , cssClass , factor , year , startYear , endYear , beforeFn ) {
var html = '' ;
var step = factor / 10 ;
var view = this . picker . find ( selector ) ;
var startVal = Math . floor ( year / factor ) * factor ;
var endVal = startVal + step * 9 ;
var focusedVal = Math . floor ( this . viewDate . getFullYear ( ) / step ) * step ;
var selected = $ . map ( this . dates , function ( d ) {
return Math . floor ( d . getUTCFullYear ( ) / step ) * step ;
} ) ;
var classes , tooltip , before ;
for ( var currVal = startVal - step ; currVal <= endVal + step ; currVal += step ) {
classes = [ cssClass ] ;
tooltip = null ;
if ( currVal === startVal - step ) {
classes . push ( 'old' ) ;
} else if ( currVal === endVal + step ) {
classes . push ( 'new' ) ;
}
if ( $ . inArray ( currVal , selected ) !== - 1 ) {
classes . push ( 'active' ) ;
}
if ( currVal < startYear || currVal > endYear ) {
classes . push ( 'disabled' ) ;
}
if ( currVal === focusedVal ) {
classes . push ( 'focused' ) ;
}
if ( beforeFn !== $ . noop ) {
before = beforeFn ( new Date ( currVal , 0 , 1 ) ) ;
if ( before === undefined ) {
before = { } ;
} else if ( typeof before === 'boolean' ) {
before = { enabled : before } ;
} else if ( typeof before === 'string' ) {
before = { classes : before } ;
}
if ( before . enabled === false ) {
classes . push ( 'disabled' ) ;
}
if ( before . classes ) {
classes = classes . concat ( before . classes . split ( /\s+/ ) ) ;
}
if ( before . tooltip ) {
tooltip = before . tooltip ;
}
}
html += '<span class="' + classes . join ( ' ' ) + '"' + ( tooltip ? ' title="' + tooltip + '"' : '' ) + '>' + currVal + '</span>' ;
}
view . find ( '.datepicker-switch' ) . text ( startVal + '-' + endVal ) ;
view . find ( 'td' ) . html ( html ) ;
} ,
fill : function ( ) {
var d = new Date ( this . viewDate ) ,
year = d . getUTCFullYear ( ) ,
month = d . getUTCMonth ( ) ,
startYear = this . o . startDate !== - Infinity ? this . o . startDate . getUTCFullYear ( ) : - Infinity ,
startMonth = this . o . startDate !== - Infinity ? this . o . startDate . getUTCMonth ( ) : - Infinity ,
endYear = this . o . endDate !== Infinity ? this . o . endDate . getUTCFullYear ( ) : Infinity ,
endMonth = this . o . endDate !== Infinity ? this . o . endDate . getUTCMonth ( ) : Infinity ,
todaytxt = dates [ this . o . language ] . today || dates [ 'en' ] . today || '' ,
cleartxt = dates [ this . o . language ] . clear || dates [ 'en' ] . clear || '' ,
titleFormat = dates [ this . o . language ] . titleFormat || dates [ 'en' ] . titleFormat ,
tooltip ,
before ;
if ( isNaN ( year ) || isNaN ( month ) )
return ;
this . picker . find ( '.datepicker-days .datepicker-switch' )
. text ( DPGlobal . formatDate ( d , titleFormat , this . o . language ) ) ;
this . picker . find ( 'tfoot .today' )
. text ( todaytxt )
. css ( 'display' , this . o . todayBtn === true || this . o . todayBtn === 'linked' ? 'table-cell' : 'none' ) ;
this . picker . find ( 'tfoot .clear' )
. text ( cleartxt )
. css ( 'display' , this . o . clearBtn === true ? 'table-cell' : 'none' ) ;
this . picker . find ( 'thead .datepicker-title' )
. text ( this . o . title )
. css ( 'display' , typeof this . o . title === 'string' && this . o . title !== '' ? 'table-cell' : 'none' ) ;
this . updateNavArrows ( ) ;
this . fillMonths ( ) ;
var prevMonth = UTCDate ( year , month , 0 ) ,
day = prevMonth . getUTCDate ( ) ;
prevMonth . setUTCDate ( day - ( prevMonth . getUTCDay ( ) - this . o . weekStart + 7 ) % 7 ) ;
var nextMonth = new Date ( prevMonth ) ;
if ( prevMonth . getUTCFullYear ( ) < 100 ) {
nextMonth . setUTCFullYear ( prevMonth . getUTCFullYear ( ) ) ;
}
nextMonth . setUTCDate ( nextMonth . getUTCDate ( ) + 42 ) ;
nextMonth = nextMonth . valueOf ( ) ;
var html = [ ] ;
var weekDay , clsName ;
while ( prevMonth . valueOf ( ) < nextMonth ) {
weekDay = prevMonth . getUTCDay ( ) ;
if ( weekDay === this . o . weekStart ) {
html . push ( '<tr>' ) ;
if ( this . o . calendarWeeks ) {
// ISO 8601: First week contains first thursday.
// ISO also states week starts on Monday, but we can be more abstract here.
var
// Start of current week: based on weekstart/current date
ws = new Date ( + prevMonth + ( this . o . weekStart - weekDay - 7 ) % 7 * 864e5 ) ,
// Thursday of this week
th = new Date ( Number ( ws ) + ( 7 + 4 - ws . getUTCDay ( ) ) % 7 * 864e5 ) ,
// First Thursday of year, year from thursday
yth = new Date ( Number ( yth = UTCDate ( th . getUTCFullYear ( ) , 0 , 1 ) ) + ( 7 + 4 - yth . getUTCDay ( ) ) % 7 * 864e5 ) ,
// Calendar week: ms between thursdays, div ms per day, div 7 days
calWeek = ( th - yth ) / 864e5 / 7 + 1 ;
html . push ( '<td class="cw">' + calWeek + '</td>' ) ;
}
}
clsName = this . getClassNames ( prevMonth ) ;
clsName . push ( 'day' ) ;
var content = prevMonth . getUTCDate ( ) ;
if ( this . o . beforeShowDay !== $ . noop ) {
before = this . o . beforeShowDay ( this . _utc _to _local ( prevMonth ) ) ;
if ( before === undefined )
before = { } ;
else if ( typeof before === 'boolean' )
before = { enabled : before } ;
else if ( typeof before === 'string' )
before = { classes : before } ;
if ( before . enabled === false )
clsName . push ( 'disabled' ) ;
if ( before . classes )
clsName = clsName . concat ( before . classes . split ( /\s+/ ) ) ;
if ( before . tooltip )
tooltip = before . tooltip ;
if ( before . content )
content = before . content ;
}
//Check if uniqueSort exists (supported by jquery >=1.12 and >=2.2)
//Fallback to unique function for older jquery versions
if ( $ . isFunction ( $ . uniqueSort ) ) {
clsName = $ . uniqueSort ( clsName ) ;
} else {
clsName = $ . unique ( clsName ) ;
}
html . push ( '<td class="' + clsName . join ( ' ' ) + '"' + ( tooltip ? ' title="' + tooltip + '"' : '' ) + ' data-date="' + prevMonth . getTime ( ) . toString ( ) + '">' + content + '</td>' ) ;
tooltip = null ;
if ( weekDay === this . o . weekEnd ) {
html . push ( '</tr>' ) ;
}
prevMonth . setUTCDate ( prevMonth . getUTCDate ( ) + 1 ) ;
}
this . picker . find ( '.datepicker-days tbody' ) . html ( html . join ( '' ) ) ;
var monthsTitle = dates [ this . o . language ] . monthsTitle || dates [ 'en' ] . monthsTitle || 'Months' ;
var months = this . picker . find ( '.datepicker-months' )
. find ( '.datepicker-switch' )
. text ( this . o . maxViewMode < 2 ? monthsTitle : year )
. end ( )
. find ( 'tbody span' ) . removeClass ( 'active' ) ;
$ . each ( this . dates , function ( i , d ) {
if ( d . getUTCFullYear ( ) === year )
months . eq ( d . getUTCMonth ( ) ) . addClass ( 'active' ) ;
} ) ;
if ( year < startYear || year > endYear ) {
months . addClass ( 'disabled' ) ;
}
if ( year === startYear ) {
months . slice ( 0 , startMonth ) . addClass ( 'disabled' ) ;
}
if ( year === endYear ) {
months . slice ( endMonth + 1 ) . addClass ( 'disabled' ) ;
}
if ( this . o . beforeShowMonth !== $ . noop ) {
var that = this ;
$ . each ( months , function ( i , month ) {
var moDate = new Date ( year , i , 1 ) ;
var before = that . o . beforeShowMonth ( moDate ) ;
if ( before === undefined )
before = { } ;
else if ( typeof before === 'boolean' )
before = { enabled : before } ;
else if ( typeof before === 'string' )
before = { classes : before } ;
if ( before . enabled === false && ! $ ( month ) . hasClass ( 'disabled' ) )
$ ( month ) . addClass ( 'disabled' ) ;
if ( before . classes )
$ ( month ) . addClass ( before . classes ) ;
if ( before . tooltip )
$ ( month ) . prop ( 'title' , before . tooltip ) ;
} ) ;
}
// Generating decade/years picker
this . _fill _yearsView (
'.datepicker-years' ,
'year' ,
10 ,
year ,
startYear ,
endYear ,
this . o . beforeShowYear
) ;
// Generating century/decades picker
this . _fill _yearsView (
'.datepicker-decades' ,
'decade' ,
100 ,
year ,
startYear ,
endYear ,
this . o . beforeShowDecade
) ;
// Generating millennium/centuries picker
this . _fill _yearsView (
'.datepicker-centuries' ,
'century' ,
1000 ,
year ,
startYear ,
endYear ,
this . o . beforeShowCentury
) ;
} ,
updateNavArrows : function ( ) {
if ( ! this . _allow _update )
return ;
var d = new Date ( this . viewDate ) ,
year = d . getUTCFullYear ( ) ,
month = d . getUTCMonth ( ) ,
startYear = this . o . startDate !== - Infinity ? this . o . startDate . getUTCFullYear ( ) : - Infinity ,
startMonth = this . o . startDate !== - Infinity ? this . o . startDate . getUTCMonth ( ) : - Infinity ,
endYear = this . o . endDate !== Infinity ? this . o . endDate . getUTCFullYear ( ) : Infinity ,
endMonth = this . o . endDate !== Infinity ? this . o . endDate . getUTCMonth ( ) : Infinity ,
prevIsDisabled ,
nextIsDisabled ,
factor = 1 ;
switch ( this . viewMode ) {
case 0 :
prevIsDisabled = year <= startYear && month <= startMonth ;
nextIsDisabled = year >= endYear && month >= endMonth ;
break ;
case 4 :
factor *= 10 ;
/* falls through */
case 3 :
factor *= 10 ;
/* falls through */
case 2 :
factor *= 10 ;
/* falls through */
case 1 :
prevIsDisabled = Math . floor ( year / factor ) * factor <= startYear ;
nextIsDisabled = Math . floor ( year / factor ) * factor + factor >= endYear ;
break ;
}
this . picker . find ( '.prev' ) . toggleClass ( 'disabled' , prevIsDisabled ) ;
this . picker . find ( '.next' ) . toggleClass ( 'disabled' , nextIsDisabled ) ;
} ,
click : function ( e ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
var target , dir , day , year , month ;
target = $ ( e . target ) ;
// Clicked on the switch
if ( target . hasClass ( 'datepicker-switch' ) && this . viewMode !== this . o . maxViewMode ) {
this . setViewMode ( this . viewMode + 1 ) ;
}
// Clicked on today button
if ( target . hasClass ( 'today' ) && ! target . hasClass ( 'day' ) ) {
this . setViewMode ( 0 ) ;
this . _setDate ( UTCToday ( ) , this . o . todayBtn === 'linked' ? null : 'view' ) ;
}
// Clicked on clear button
if ( target . hasClass ( 'clear' ) ) {
this . clearDates ( ) ;
}
if ( ! target . hasClass ( 'disabled' ) ) {
// Clicked on a month, year, decade, century
if ( target . hasClass ( 'month' )
|| target . hasClass ( 'year' )
|| target . hasClass ( 'decade' )
|| target . hasClass ( 'century' ) ) {
this . viewDate . setUTCDate ( 1 ) ;
day = 1 ;
if ( this . viewMode === 1 ) {
month = target . parent ( ) . find ( 'span' ) . index ( target ) ;
year = this . viewDate . getUTCFullYear ( ) ;
this . viewDate . setUTCMonth ( month ) ;
} else {
month = 0 ;
year = Number ( target . text ( ) ) ;
this . viewDate . setUTCFullYear ( year ) ;
}
this . _trigger ( DPGlobal . viewModes [ this . viewMode - 1 ] . e , this . viewDate ) ;
if ( this . viewMode === this . o . minViewMode ) {
this . _setDate ( UTCDate ( year , month , day ) ) ;
} else {
this . setViewMode ( this . viewMode - 1 ) ;
this . fill ( ) ;
}
}
}
if ( this . picker . is ( ':visible' ) && this . _focused _from ) {
this . _focused _from . focus ( ) ;
}
delete this . _focused _from ;
} ,
dayCellClick : function ( e ) {
var $target = $ ( e . currentTarget ) ;
var timestamp = $target . data ( 'date' ) ;
var date = new Date ( timestamp ) ;
if ( this . o . updateViewDate ) {
if ( date . getUTCFullYear ( ) !== this . viewDate . getUTCFullYear ( ) ) {
this . _trigger ( 'changeYear' , this . viewDate ) ;
}
if ( date . getUTCMonth ( ) !== this . viewDate . getUTCMonth ( ) ) {
this . _trigger ( 'changeMonth' , this . viewDate ) ;
}
}
this . _setDate ( date ) ;
} ,
// Clicked on prev or next
navArrowsClick : function ( e ) {
var $target = $ ( e . currentTarget ) ;
var dir = $target . hasClass ( 'prev' ) ? - 1 : 1 ;
if ( this . viewMode !== 0 ) {
dir *= DPGlobal . viewModes [ this . viewMode ] . navStep * 12 ;
}
this . viewDate = this . moveMonth ( this . viewDate , dir ) ;
this . _trigger ( DPGlobal . viewModes [ this . viewMode ] . e , this . viewDate ) ;
this . fill ( ) ;
} ,
_toggle _multidate : function ( date ) {
var ix = this . dates . contains ( date ) ;
if ( ! date ) {
this . dates . clear ( ) ;
}
if ( ix !== - 1 ) {
if ( this . o . multidate === true || this . o . multidate > 1 || this . o . toggleActive ) {
this . dates . remove ( ix ) ;
}
} else if ( this . o . multidate === false ) {
this . dates . clear ( ) ;
this . dates . push ( date ) ;
}
else {
this . dates . push ( date ) ;
}
if ( typeof this . o . multidate === 'number' )
while ( this . dates . length > this . o . multidate )
this . dates . remove ( 0 ) ;
} ,
_setDate : function ( date , which ) {
if ( ! which || which === 'date' )
this . _toggle _multidate ( date && new Date ( date ) ) ;
if ( ( ! which && this . o . updateViewDate ) || which === 'view' )
this . viewDate = date && new Date ( date ) ;
this . fill ( ) ;
this . setValue ( ) ;
if ( ! which || which !== 'view' ) {
this . _trigger ( 'changeDate' ) ;
}
this . inputField . trigger ( 'change' ) ;
if ( this . o . autoclose && ( ! which || which === 'date' ) ) {
this . hide ( ) ;
}
} ,
moveDay : function ( date , dir ) {
var newDate = new Date ( date ) ;
newDate . setUTCDate ( date . getUTCDate ( ) + dir ) ;
return newDate ;
} ,
moveWeek : function ( date , dir ) {
return this . moveDay ( date , dir * 7 ) ;
} ,
moveMonth : function ( date , dir ) {
if ( ! isValidDate ( date ) )
return this . o . defaultViewDate ;
if ( ! dir )
return date ;
var new _date = new Date ( date . valueOf ( ) ) ,
day = new _date . getUTCDate ( ) ,
month = new _date . getUTCMonth ( ) ,
mag = Math . abs ( dir ) ,
new _month , test ;
dir = dir > 0 ? 1 : - 1 ;
if ( mag === 1 ) {
test = dir === - 1
// If going back one month, make sure month is not current month
// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
? function ( ) {
return new _date . getUTCMonth ( ) === month ;
}
// If going forward one month, make sure month is as expected
// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
: function ( ) {
return new _date . getUTCMonth ( ) !== new _month ;
} ;
new _month = month + dir ;
new _date . setUTCMonth ( new _month ) ;
// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
new _month = ( new _month + 12 ) % 12 ;
}
else {
// For magnitudes >1, move one month at a time...
for ( var i = 0 ; i < mag ; i ++ )
// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
new _date = this . moveMonth ( new _date , dir ) ;
// ...then reset the day, keeping it in the new month
new _month = new _date . getUTCMonth ( ) ;
new _date . setUTCDate ( day ) ;
test = function ( ) {
return new _month !== new _date . getUTCMonth ( ) ;
} ;
}
// Common date-resetting loop -- if date is beyond end of month, make it
// end of month
while ( test ( ) ) {
new _date . setUTCDate ( -- day ) ;
new _date . setUTCMonth ( new _month ) ;
}
return new _date ;
} ,
moveYear : function ( date , dir ) {
return this . moveMonth ( date , dir * 12 ) ;
} ,
moveAvailableDate : function ( date , dir , fn ) {
do {
date = this [ fn ] ( date , dir ) ;
if ( ! this . dateWithinRange ( date ) )
return false ;
fn = 'moveDay' ;
}
while ( this . dateIsDisabled ( date ) ) ;
return date ;
} ,
weekOfDateIsDisabled : function ( date ) {
return $ . inArray ( date . getUTCDay ( ) , this . o . daysOfWeekDisabled ) !== - 1 ;
} ,
dateIsDisabled : function ( date ) {
return (
this . weekOfDateIsDisabled ( date ) ||
$ . grep ( this . o . datesDisabled , function ( d ) {
return isUTCEquals ( date , d ) ;
} ) . length > 0
) ;
} ,
dateWithinRange : function ( date ) {
return date >= this . o . startDate && date <= this . o . endDate ;
} ,
keydown : function ( e ) {
if ( ! this . picker . is ( ':visible' ) ) {
if ( e . keyCode === 40 || e . keyCode === 27 ) { // allow down to re-show picker
this . show ( ) ;
e . stopPropagation ( ) ;
}
return ;
}
var dateChanged = false ,
dir , newViewDate ,
focusDate = this . focusDate || this . viewDate ;
switch ( e . keyCode ) {
case 27 : // escape
if ( this . focusDate ) {
this . focusDate = null ;
this . viewDate = this . dates . get ( - 1 ) || this . viewDate ;
this . fill ( ) ;
}
else
this . hide ( ) ;
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
break ;
case 37 : // left
case 38 : // up
case 39 : // right
case 40 : // down
if ( ! this . o . keyboardNavigation || this . o . daysOfWeekDisabled . length === 7 )
break ;
dir = e . keyCode === 37 || e . keyCode === 38 ? - 1 : 1 ;
if ( this . viewMode === 0 ) {
if ( e . ctrlKey ) {
newViewDate = this . moveAvailableDate ( focusDate , dir , 'moveYear' ) ;
if ( newViewDate )
this . _trigger ( 'changeYear' , this . viewDate ) ;
} else if ( e . shiftKey ) {
newViewDate = this . moveAvailableDate ( focusDate , dir , 'moveMonth' ) ;
if ( newViewDate )
this . _trigger ( 'changeMonth' , this . viewDate ) ;
} else if ( e . keyCode === 37 || e . keyCode === 39 ) {
newViewDate = this . moveAvailableDate ( focusDate , dir , 'moveDay' ) ;
} else if ( ! this . weekOfDateIsDisabled ( focusDate ) ) {
newViewDate = this . moveAvailableDate ( focusDate , dir , 'moveWeek' ) ;
}
} else if ( this . viewMode === 1 ) {
if ( e . keyCode === 38 || e . keyCode === 40 ) {
dir = dir * 4 ;
}
newViewDate = this . moveAvailableDate ( focusDate , dir , 'moveMonth' ) ;
} else if ( this . viewMode === 2 ) {
if ( e . keyCode === 38 || e . keyCode === 40 ) {
dir = dir * 4 ;
}
newViewDate = this . moveAvailableDate ( focusDate , dir , 'moveYear' ) ;
}
if ( newViewDate ) {
this . focusDate = this . viewDate = newViewDate ;
this . setValue ( ) ;
this . fill ( ) ;
e . preventDefault ( ) ;
}
break ;
case 13 : // enter
if ( ! this . o . forceParse )
break ;
focusDate = this . focusDate || this . dates . get ( - 1 ) || this . viewDate ;
if ( this . o . keyboardNavigation ) {
this . _toggle _multidate ( focusDate ) ;
dateChanged = true ;
}
this . focusDate = null ;
this . viewDate = this . dates . get ( - 1 ) || this . viewDate ;
this . setValue ( ) ;
this . fill ( ) ;
if ( this . picker . is ( ':visible' ) ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
if ( this . o . autoclose )
this . hide ( ) ;
}
break ;
case 9 : // tab
this . focusDate = null ;
this . viewDate = this . dates . get ( - 1 ) || this . viewDate ;
this . fill ( ) ;
this . hide ( ) ;
break ;
}
if ( dateChanged ) {
if ( this . dates . length )
this . _trigger ( 'changeDate' ) ;
else
this . _trigger ( 'clearDate' ) ;
this . inputField . trigger ( 'change' ) ;
}
} ,
setViewMode : function ( viewMode ) {
this . viewMode = viewMode ;
this . picker
. children ( 'div' )
. hide ( )
. filter ( '.datepicker-' + DPGlobal . viewModes [ this . viewMode ] . clsName )
. show ( ) ;
this . updateNavArrows ( ) ;
this . _trigger ( 'changeViewMode' , new Date ( this . viewDate ) ) ;
}
} ;
var DateRangePicker = function ( element , options ) {
$ . data ( element , 'datepicker' , this ) ;
this . element = $ ( element ) ;
this . inputs = $ . map ( options . inputs , function ( i ) {
return i . jquery ? i [ 0 ] : i ;
} ) ;
delete options . inputs ;
this . keepEmptyValues = options . keepEmptyValues ;
delete options . keepEmptyValues ;
datepickerPlugin . call ( $ ( this . inputs ) , options )
. on ( 'changeDate' , $ . proxy ( this . dateUpdated , this ) ) ;
this . pickers = $ . map ( this . inputs , function ( i ) {
return $ . data ( i , 'datepicker' ) ;
} ) ;
this . updateDates ( ) ;
} ;
DateRangePicker . prototype = {
updateDates : function ( ) {
this . dates = $ . map ( this . pickers , function ( i ) {
return i . getUTCDate ( ) ;
} ) ;
this . updateRanges ( ) ;
} ,
updateRanges : function ( ) {
var range = $ . map ( this . dates , function ( d ) {
return d . valueOf ( ) ;
} ) ;
$ . each ( this . pickers , function ( i , p ) {
p . setRange ( range ) ;
} ) ;
} ,
dateUpdated : function ( e ) {
// `this.updating` is a workaround for preventing infinite recursion
// between `changeDate` triggering and `setUTCDate` calling. Until
// there is a better mechanism.
if ( this . updating )
return ;
this . updating = true ;
var dp = $ . data ( e . target , 'datepicker' ) ;
if ( dp === undefined ) {
return ;
}
var new _date = dp . getUTCDate ( ) ,
keep _empty _values = this . keepEmptyValues ,
i = $ . inArray ( e . target , this . inputs ) ,
j = i - 1 ,
k = i + 1 ,
l = this . inputs . length ;
if ( i === - 1 )
return ;
$ . each ( this . pickers , function ( i , p ) {
if ( ! p . getUTCDate ( ) && ( p === dp || ! keep _empty _values ) )
p . setUTCDate ( new _date ) ;
} ) ;
if ( new _date < this . dates [ j ] ) {
// Date being moved earlier/left
while ( j >= 0 && new _date < this . dates [ j ] ) {
this . pickers [ j -- ] . setUTCDate ( new _date ) ;
}
} else if ( new _date > this . dates [ k ] ) {
// Date being moved later/right
while ( k < l && new _date > this . dates [ k ] ) {
this . pickers [ k ++ ] . setUTCDate ( new _date ) ;
}
}
this . updateDates ( ) ;
delete this . updating ;
} ,
destroy : function ( ) {
$ . map ( this . pickers , function ( p ) { p . destroy ( ) ; } ) ;
$ ( this . inputs ) . off ( 'changeDate' , this . dateUpdated ) ;
delete this . element . data ( ) . datepicker ;
} ,
remove : alias ( 'destroy' , 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead' )
} ;
function opts _from _el ( el , prefix ) {
// Derive options from element data-attrs
var data = $ ( el ) . data ( ) ,
out = { } , inkey ,
replace = new RegExp ( '^' + prefix . toLowerCase ( ) + '([A-Z])' ) ;
prefix = new RegExp ( '^' + prefix . toLowerCase ( ) ) ;
function re _lower ( _ , a ) {
return a . toLowerCase ( ) ;
}
for ( var key in data )
if ( prefix . test ( key ) ) {
inkey = key . replace ( replace , re _lower ) ;
out [ inkey ] = data [ key ] ;
}
return out ;
}
function opts _from _locale ( lang ) {
// Derive options from locale plugins
var out = { } ;
// Check if "de-DE" style date is available, if not language should
// fallback to 2 letter code eg "de"
if ( ! dates [ lang ] ) {
lang = lang . split ( '-' ) [ 0 ] ;
if ( ! dates [ lang ] )
return ;
}
var d = dates [ lang ] ;
$ . each ( locale _opts , function ( i , k ) {
if ( k in d )
out [ k ] = d [ k ] ;
} ) ;
return out ;
}
var old = $ . fn . datepicker ;
var datepickerPlugin = function ( option ) {
var args = Array . apply ( null , arguments ) ;
args . shift ( ) ;
var internal _return ;
this . each ( function ( ) {
var $this = $ ( this ) ,
data = $this . data ( 'datepicker' ) ,
options = typeof option === 'object' && option ;
if ( ! data ) {
var elopts = opts _from _el ( this , 'date' ) ,
// Preliminary otions
xopts = $ . extend ( { } , defaults , elopts , options ) ,
locopts = opts _from _locale ( xopts . language ) ,
// Options priority: js args, data-attrs, locales, defaults
opts = $ . extend ( { } , defaults , locopts , elopts , options ) ;
if ( $this . hasClass ( 'input-daterange' ) || opts . inputs ) {
$ . extend ( opts , {
inputs : opts . inputs || $this . find ( 'input' ) . toArray ( )
} ) ;
data = new DateRangePicker ( this , opts ) ;
}
else {
data = new Datepicker ( this , opts ) ;
}
$this . data ( 'datepicker' , data ) ;
}
if ( typeof option === 'string' && typeof data [ option ] === 'function' ) {
internal _return = data [ option ] . apply ( data , args ) ;
}
} ) ;
if (
internal _return === undefined ||
internal _return instanceof Datepicker ||
internal _return instanceof DateRangePicker
)
return this ;
if ( this . length > 1 )
throw new Error ( 'Using only allowed for the collection of a single element (' + option + ' function)' ) ;
else
return internal _return ;
} ;
$ . fn . datepicker = datepickerPlugin ;
var defaults = $ . fn . datepicker . defaults = {
assumeNearbyYear : false ,
autoclose : false ,
beforeShowDay : $ . noop ,
beforeShowMonth : $ . noop ,
beforeShowYear : $ . noop ,
beforeShowDecade : $ . noop ,
beforeShowCentury : $ . noop ,
calendarWeeks : false ,
clearBtn : false ,
toggleActive : false ,
daysOfWeekDisabled : [ ] ,
daysOfWeekHighlighted : [ ] ,
datesDisabled : [ ] ,
endDate : Infinity ,
forceParse : true ,
format : 'mm/dd/yyyy' ,
keepEmptyValues : false ,
keyboardNavigation : true ,
language : 'en' ,
minViewMode : 0 ,
maxViewMode : 4 ,
multidate : false ,
multidateSeparator : ',' ,
orientation : "auto" ,
rtl : false ,
startDate : - Infinity ,
startView : 0 ,
todayBtn : false ,
todayHighlight : false ,
updateViewDate : true ,
weekStart : 0 ,
disableTouchKeyboard : false ,
enableOnReadonly : true ,
showOnFocus : true ,
zIndexOffset : 10 ,
container : 'body' ,
immediateUpdates : false ,
title : '' ,
templates : {
leftArrow : '«' ,
rightArrow : '»'
} ,
showWeekDays : true
} ;
var locale _opts = $ . fn . datepicker . locale _opts = [
'format' ,
'rtl' ,
'weekStart'
] ;
$ . fn . datepicker . Constructor = Datepicker ;
var dates = $ . fn . datepicker . dates = {
en : {
days : [ "Sunday" , "Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" ] ,
daysShort : [ "Sun" , "Mon" , "Tue" , "Wed" , "Thu" , "Fri" , "Sat" ] ,
daysMin : [ "Su" , "Mo" , "Tu" , "We" , "Th" , "Fr" , "Sa" ] ,
months : [ "January" , "February" , "March" , "April" , "May" , "June" , "July" , "August" , "September" , "October" , "November" , "December" ] ,
monthsShort : [ "Jan" , "Feb" , "Mar" , "Apr" , "May" , "Jun" , "Jul" , "Aug" , "Sep" , "Oct" , "Nov" , "Dec" ] ,
today : "Today" ,
clear : "Clear" ,
titleFormat : "MM yyyy"
}
} ;
var DPGlobal = {
viewModes : [
{
names : [ 'days' , 'month' ] ,
clsName : 'days' ,
e : 'changeMonth'
} ,
{
names : [ 'months' , 'year' ] ,
clsName : 'months' ,
e : 'changeYear' ,
navStep : 1
} ,
{
names : [ 'years' , 'decade' ] ,
clsName : 'years' ,
e : 'changeDecade' ,
navStep : 10
} ,
{
names : [ 'decades' , 'century' ] ,
clsName : 'decades' ,
e : 'changeCentury' ,
navStep : 100
} ,
{
names : [ 'centuries' , 'millennium' ] ,
clsName : 'centuries' ,
e : 'changeMillennium' ,
navStep : 1000
}
] ,
validParts : /dd?|DD?|mm?|MM?|yy(?:yy)?/g ,
nonpunctuation : /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g ,
parseFormat : function ( format ) {
if ( typeof format . toValue === 'function' && typeof format . toDisplay === 'function' )
return format ;
// IE treats \0 as a string end in inputs (truncating the value),
// so it's a bad format delimiter, anyway
var separators = format . replace ( this . validParts , '\0' ) . split ( '\0' ) ,
parts = format . match ( this . validParts ) ;
if ( ! separators || ! separators . length || ! parts || parts . length === 0 ) {
throw new Error ( "Invalid date format." ) ;
}
return { separators : separators , parts : parts } ;
} ,
parseDate : function ( date , format , language , assumeNearby ) {
if ( ! date )
return undefined ;
if ( date instanceof Date )
return date ;
if ( typeof format === 'string' )
format = DPGlobal . parseFormat ( format ) ;
if ( format . toValue )
return format . toValue ( date , format , language ) ;
var fn _map = {
d : 'moveDay' ,
m : 'moveMonth' ,
w : 'moveWeek' ,
y : 'moveYear'
} ,
dateAliases = {
yesterday : '-1d' ,
today : '+0d' ,
tomorrow : '+1d'
} ,
parts , part , dir , i , fn ;
if ( date in dateAliases ) {
date = dateAliases [ date ] ;
}
if ( /^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i . test ( date ) ) {
parts = date . match ( /([\-+]\d+)([dmwy])/gi ) ;
date = new Date ( ) ;
for ( i = 0 ; i < parts . length ; i ++ ) {
part = parts [ i ] . match ( /([\-+]\d+)([dmwy])/i ) ;
dir = Number ( part [ 1 ] ) ;
fn = fn _map [ part [ 2 ] . toLowerCase ( ) ] ;
date = Datepicker . prototype [ fn ] ( date , dir ) ;
}
return Datepicker . prototype . _zero _utc _time ( date ) ;
}
parts = date && date . match ( this . nonpunctuation ) || [ ] ;
function applyNearbyYear ( year , threshold ) {
if ( threshold === true )
threshold = 10 ;
// if year is 2 digits or less, than the user most likely is trying to get a recent century
if ( year < 100 ) {
year += 2000 ;
// if the new year is more than threshold years in advance, use last century
if ( year > ( ( new Date ( ) ) . getFullYear ( ) + threshold ) ) {
year -= 100 ;
}
}
return year ;
}
var parsed = { } ,
setters _order = [ 'yyyy' , 'yy' , 'M' , 'MM' , 'm' , 'mm' , 'd' , 'dd' ] ,
setters _map = {
yyyy : function ( d , v ) {
return d . setUTCFullYear ( assumeNearby ? applyNearbyYear ( v , assumeNearby ) : v ) ;
} ,
m : function ( d , v ) {
if ( isNaN ( d ) )
return d ;
v -= 1 ;
while ( v < 0 ) v += 12 ;
v %= 12 ;
d . setUTCMonth ( v ) ;
while ( d . getUTCMonth ( ) !== v )
d . setUTCDate ( d . getUTCDate ( ) - 1 ) ;
return d ;
} ,
d : function ( d , v ) {
return d . setUTCDate ( v ) ;
}
} ,
val , filtered ;
setters _map [ 'yy' ] = setters _map [ 'yyyy' ] ;
setters _map [ 'M' ] = setters _map [ 'MM' ] = setters _map [ 'mm' ] = setters _map [ 'm' ] ;
setters _map [ 'dd' ] = setters _map [ 'd' ] ;
date = UTCToday ( ) ;
var fparts = format . parts . slice ( ) ;
// Remove noop parts
if ( parts . length !== fparts . length ) {
fparts = $ ( fparts ) . filter ( function ( i , p ) {
return $ . inArray ( p , setters _order ) !== - 1 ;
} ) . toArray ( ) ;
}
// Process remainder
function match _part ( ) {
var m = this . slice ( 0 , parts [ i ] . length ) ,
p = parts [ i ] . slice ( 0 , m . length ) ;
return m . toLowerCase ( ) === p . toLowerCase ( ) ;
}
if ( parts . length === fparts . length ) {
var cnt ;
for ( i = 0 , cnt = fparts . length ; i < cnt ; i ++ ) {
val = parseInt ( parts [ i ] , 10 ) ;
part = fparts [ i ] ;
if ( isNaN ( val ) ) {
switch ( part ) {
case 'MM' :
filtered = $ ( dates [ language ] . months ) . filter ( match _part ) ;
val = $ . inArray ( filtered [ 0 ] , dates [ language ] . months ) + 1 ;
break ;
case 'M' :
filtered = $ ( dates [ language ] . monthsShort ) . filter ( match _part ) ;
val = $ . inArray ( filtered [ 0 ] , dates [ language ] . monthsShort ) + 1 ;
break ;
}
}
parsed [ part ] = val ;
}
var _date , s ;
for ( i = 0 ; i < setters _order . length ; i ++ ) {
s = setters _order [ i ] ;
if ( s in parsed && ! isNaN ( parsed [ s ] ) ) {
_date = new Date ( date ) ;
setters _map [ s ] ( _date , parsed [ s ] ) ;
if ( ! isNaN ( _date ) )
date = _date ;
}
}
}
return date ;
} ,
formatDate : function ( date , format , language ) {
if ( ! date )
return '' ;
if ( typeof format === 'string' )
format = DPGlobal . parseFormat ( format ) ;
if ( format . toDisplay )
return format . toDisplay ( date , format , language ) ;
var val = {
d : date . getUTCDate ( ) ,
D : dates [ language ] . daysShort [ date . getUTCDay ( ) ] ,
DD : dates [ language ] . days [ date . getUTCDay ( ) ] ,
m : date . getUTCMonth ( ) + 1 ,
M : dates [ language ] . monthsShort [ date . getUTCMonth ( ) ] ,
MM : dates [ language ] . months [ date . getUTCMonth ( ) ] ,
yy : date . getUTCFullYear ( ) . toString ( ) . substring ( 2 ) ,
yyyy : date . getUTCFullYear ( )
} ;
val . dd = ( val . d < 10 ? '0' : '' ) + val . d ;
val . mm = ( val . m < 10 ? '0' : '' ) + val . m ;
date = [ ] ;
var seps = $ . extend ( [ ] , format . separators ) ;
for ( var i = 0 , cnt = format . parts . length ; i <= cnt ; i ++ ) {
if ( seps . length )
date . push ( seps . shift ( ) ) ;
date . push ( val [ format . parts [ i ] ] ) ;
}
return date . join ( '' ) ;
} ,
headTemplate : '<thead>' +
'<tr>' +
'<th colspan="7" class="datepicker-title"></th>' +
'</tr>' +
'<tr>' +
'<th class="prev">' + defaults . templates . leftArrow + '</th>' +
'<th colspan="5" class="datepicker-switch"></th>' +
'<th class="next">' + defaults . templates . rightArrow + '</th>' +
'</tr>' +
'</thead>' ,
contTemplate : '<tbody><tr><td colspan="7"></td></tr></tbody>' ,
footTemplate : '<tfoot>' +
'<tr>' +
'<th colspan="7" class="today"></th>' +
'</tr>' +
'<tr>' +
'<th colspan="7" class="clear"></th>' +
'</tr>' +
'</tfoot>'
} ;
DPGlobal . template = '<div class="datepicker">' +
'<div class="datepicker-days">' +
'<table class="table-condensed">' +
DPGlobal . headTemplate +
'<tbody></tbody>' +
DPGlobal . footTemplate +
'</table>' +
'</div>' +
'<div class="datepicker-months">' +
'<table class="table-condensed">' +
DPGlobal . headTemplate +
DPGlobal . contTemplate +
DPGlobal . footTemplate +
'</table>' +
'</div>' +
'<div class="datepicker-years">' +
'<table class="table-condensed">' +
DPGlobal . headTemplate +
DPGlobal . contTemplate +
DPGlobal . footTemplate +
'</table>' +
'</div>' +
'<div class="datepicker-decades">' +
'<table class="table-condensed">' +
DPGlobal . headTemplate +
DPGlobal . contTemplate +
DPGlobal . footTemplate +
'</table>' +
'</div>' +
'<div class="datepicker-centuries">' +
'<table class="table-condensed">' +
DPGlobal . headTemplate +
DPGlobal . contTemplate +
DPGlobal . footTemplate +
'</table>' +
'</div>' +
'</div>' ;
$ . fn . datepicker . DPGlobal = DPGlobal ;
/ * D A T E P I C K E R N O C O N F L I C T
* === === === === === === = * /
$ . fn . datepicker . noConflict = function ( ) {
$ . fn . datepicker = old ;
return this ;
} ;
/ * D A T E P I C K E R V E R S I O N
* === === === === === === = * /
$ . fn . datepicker . version = '1.7.1' ;
$ . fn . datepicker . deprecated = function ( msg ) {
var console = window . console ;
if ( console && console . warn ) {
console . warn ( 'DEPRECATED: ' + msg ) ;
}
} ;
/ * D A T E P I C K E R D A T A - A P I
* === === === === === === * /
$ ( document ) . on (
'focus.datepicker.data-api click.datepicker.data-api' ,
'[data-provide="datepicker"]' ,
function ( e ) {
var $this = $ ( this ) ;
if ( $this . data ( 'datepicker' ) )
return ;
e . preventDefault ( ) ;
// component click requires us to explicitly show it
datepickerPlugin . call ( $this , 'show' ) ;
}
) ;
$ ( function ( ) {
datepickerPlugin . call ( $ ( '[data-provide="datepicker-inline"]' ) ) ;
} ) ;
} ) ) ;
/ * !
* iCheck v1 . 0.2 , http : //git.io/arlzeA
* === === === === === === === === === === === ==
* Powerful jQuery and Zepto plugin for checkboxes and radio buttons customization
*
* ( c ) 2013 Damir Sultanov , http : //fronteed.com
* MIT Licensed
* /
( function ( $ ) {
// Cached vars
var _iCheck = 'iCheck' ,
_iCheckHelper = _iCheck + '-helper' ,
_checkbox = 'checkbox' ,
_radio = 'radio' ,
_checked = 'checked' ,
_unchecked = 'un' + _checked ,
_disabled = 'disabled' ,
_determinate = 'determinate' ,
_indeterminate = 'in' + _determinate ,
_update = 'update' ,
_type = 'type' ,
_click = 'click' ,
_touch = 'touchbegin.i touchend.i' ,
_add = 'addClass' ,
_remove = 'removeClass' ,
_callback = 'trigger' ,
_label = 'label' ,
_cursor = 'cursor' ,
_mobile = /ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i . test ( navigator . userAgent ) ;
// Plugin init
$ . fn [ _iCheck ] = function ( options , fire ) {
// Walker
var handle = 'input[type="' + _checkbox + '"], input[type="' + _radio + '"]' ,
stack = $ ( ) ,
walker = function ( object ) {
object . each ( function ( ) {
var self = $ ( this ) ;
if ( self . is ( handle ) ) {
stack = stack . add ( self ) ;
} else {
stack = stack . add ( self . find ( handle ) ) ;
}
} ) ;
} ;
// Check if we should operate with some method
if ( /^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i . test ( options ) ) {
// Normalize method's name
options = options . toLowerCase ( ) ;
// Find checkboxes and radio buttons
walker ( this ) ;
return stack . each ( function ( ) {
var self = $ ( this ) ;
if ( options == 'destroy' ) {
tidy ( self , 'ifDestroyed' ) ;
} else {
operate ( self , true , options ) ;
}
// Fire method's callback
if ( $ . isFunction ( fire ) ) {
fire ( ) ;
}
} ) ;
// Customization
} else if ( typeof options == 'object' || ! options ) {
// Check if any options were passed
var settings = $ . extend ( {
checkedClass : _checked ,
disabledClass : _disabled ,
indeterminateClass : _indeterminate ,
labelHover : true
} , options ) ,
selector = settings . handle ,
hoverClass = settings . hoverClass || 'hover' ,
focusClass = settings . focusClass || 'focus' ,
activeClass = settings . activeClass || 'active' ,
labelHover = ! ! settings . labelHover ,
labelHoverClass = settings . labelHoverClass || 'hover' ,
// Setup clickable area
area = ( '' + settings . increaseArea ) . replace ( '%' , '' ) | 0 ;
// Selector limit
if ( selector == _checkbox || selector == _radio ) {
handle = 'input[type="' + selector + '"]' ;
}
// Clickable area limit
if ( area < - 50 ) {
area = - 50 ;
}
// Walk around the selector
walker ( this ) ;
return stack . each ( function ( ) {
var self = $ ( this ) ;
// If already customized
tidy ( self ) ;
var node = this ,
id = node . id ,
// Layer styles
offset = - area + '%' ,
size = 100 + ( area * 2 ) + '%' ,
layer = {
position : 'absolute' ,
top : offset ,
left : offset ,
display : 'block' ,
width : size ,
height : size ,
margin : 0 ,
padding : 0 ,
background : '#fff' ,
border : 0 ,
opacity : 0
} ,
// Choose how to hide input
hide = _mobile ? {
position : 'absolute' ,
visibility : 'hidden'
} : area ? layer : {
position : 'absolute' ,
opacity : 0
} ,
// Get proper class
className = node [ _type ] == _checkbox ? settings . checkboxClass || 'i' + _checkbox : settings . radioClass || 'i' + _radio ,
// Find assigned labels
label = $ ( _label + '[for="' + id + '"]' ) . add ( self . closest ( _label ) ) ,
// Check ARIA option
aria = ! ! settings . aria ,
// Set ARIA placeholder
ariaID = _iCheck + '-' + Math . random ( ) . toString ( 36 ) . substr ( 2 , 6 ) ,
// Parent & helper
parent = '<div class="' + className + '" ' + ( aria ? 'role="' + node [ _type ] + '" ' : '' ) ,
helper ;
// Set ARIA "labelledby"
if ( aria ) {
label . each ( function ( ) {
parent += 'aria-labelledby="' ;
if ( this . id ) {
parent += this . id ;
} else {
this . id = ariaID ;
parent += ariaID ;
}
parent += '"' ;
} ) ;
}
// Wrap input
parent = self . wrap ( parent + '/>' ) [ _callback ] ( 'ifCreated' ) . parent ( ) . append ( settings . insert ) ;
// Layer addition
helper = $ ( '<ins class="' + _iCheckHelper + '"/>' ) . css ( layer ) . appendTo ( parent ) ;
// Finalize customization
self . data ( _iCheck , { o : settings , s : self . attr ( 'style' ) } ) . css ( hide ) ;
! ! settings . inheritClass && parent [ _add ] ( node . className || '' ) ;
! ! settings . inheritID && id && parent . attr ( 'id' , _iCheck + '-' + id ) ;
parent . css ( 'position' ) == 'static' && parent . css ( 'position' , 'relative' ) ;
operate ( self , true , _update ) ;
// Label events
if ( label . length ) {
label . on ( _click + '.i mouseover.i mouseout.i ' + _touch , function ( event ) {
var type = event [ _type ] ,
item = $ ( this ) ;
// Do nothing if input is disabled
if ( ! node [ _disabled ] ) {
// Click
if ( type == _click ) {
if ( $ ( event . target ) . is ( 'a' ) ) {
return ;
}
operate ( self , false , true ) ;
// Hover state
} else if ( labelHover ) {
// mouseout|touchend
if ( /ut|nd/ . test ( type ) ) {
parent [ _remove ] ( hoverClass ) ;
item [ _remove ] ( labelHoverClass ) ;
} else {
parent [ _add ] ( hoverClass ) ;
item [ _add ] ( labelHoverClass ) ;
}
}
if ( _mobile ) {
event . stopPropagation ( ) ;
} else {
return false ;
}
}
} ) ;
}
// Input events
self . on ( _click + '.i focus.i blur.i keyup.i keydown.i keypress.i' , function ( event ) {
var type = event [ _type ] ,
key = event . keyCode ;
// Click
if ( type == _click ) {
return false ;
// Keydown
} else if ( type == 'keydown' && key == 32 ) {
if ( ! ( node [ _type ] == _radio && node [ _checked ] ) ) {
if ( node [ _checked ] ) {
off ( self , _checked ) ;
} else {
on ( self , _checked ) ;
}
}
return false ;
// Keyup
} else if ( type == 'keyup' && node [ _type ] == _radio ) {
! node [ _checked ] && on ( self , _checked ) ;
// Focus/blur
} else if ( /us|ur/ . test ( type ) ) {
parent [ type == 'blur' ? _remove : _add ] ( focusClass ) ;
}
} ) ;
// Helper events
helper . on ( _click + ' mousedown mouseup mouseover mouseout ' + _touch , function ( event ) {
var type = event [ _type ] ,
// mousedown|mouseup
toggle = /wn|up/ . test ( type ) ? activeClass : hoverClass ;
// Do nothing if input is disabled
if ( ! node [ _disabled ] ) {
// Click
if ( type == _click ) {
operate ( self , false , true ) ;
// Active and hover states
} else {
// State is on
if ( /wn|er|in/ . test ( type ) ) {
// mousedown|mouseover|touchbegin
parent [ _add ] ( toggle ) ;
// State is off
} else {
parent [ _remove ] ( toggle + ' ' + activeClass ) ;
}
// Label hover
if ( label . length && labelHover && toggle == hoverClass ) {
// mouseout|touchend
label [ /ut|nd/ . test ( type ) ? _remove : _add ] ( labelHoverClass ) ;
}
}
if ( _mobile ) {
event . stopPropagation ( ) ;
} else {
return false ;
}
}
} ) ;
} ) ;
} else {
return this ;
}
} ;
// Do something with inputs
function operate ( input , direct , method ) {
var node = input [ 0 ] ,
state = /er/ . test ( method ) ? _indeterminate : /bl/ . test ( method ) ? _disabled : _checked ,
active = method == _update ? {
checked : node [ _checked ] ,
disabled : node [ _disabled ] ,
indeterminate : input . attr ( _indeterminate ) == 'true' || input . attr ( _determinate ) == 'false'
} : node [ state ] ;
// Check, disable or indeterminate
if ( /^(ch|di|in)/ . test ( method ) && ! active ) {
on ( input , state ) ;
// Uncheck, enable or determinate
} else if ( /^(un|en|de)/ . test ( method ) && active ) {
off ( input , state ) ;
// Update
} else if ( method == _update ) {
// Handle states
for ( var each in active ) {
if ( active [ each ] ) {
on ( input , each , true ) ;
} else {
off ( input , each , true ) ;
}
}
} else if ( ! direct || method == 'toggle' ) {
// Helper or label was clicked
if ( ! direct ) {
input [ _callback ] ( 'ifClicked' ) ;
}
// Toggle checked state
if ( active ) {
if ( node [ _type ] !== _radio ) {
off ( input , state ) ;
}
} else {
on ( input , state ) ;
}
}
}
// Add checked, disabled or indeterminate state
function on ( input , state , keep ) {
var node = input [ 0 ] ,
parent = input . parent ( ) ,
checked = state == _checked ,
indeterminate = state == _indeterminate ,
disabled = state == _disabled ,
callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled' ,
regular = option ( input , callback + capitalize ( node [ _type ] ) ) ,
specific = option ( input , state + capitalize ( node [ _type ] ) ) ;
// Prevent unnecessary actions
if ( node [ state ] !== true ) {
// Toggle assigned radio buttons
if ( ! keep && state == _checked && node [ _type ] == _radio && node . name ) {
var form = input . closest ( 'form' ) ,
inputs = 'input[name="' + node . name + '"]' ;
inputs = form . length ? form . find ( inputs ) : $ ( inputs ) ;
inputs . each ( function ( ) {
if ( this !== node && $ ( this ) . data ( _iCheck ) ) {
off ( $ ( this ) , state ) ;
}
} ) ;
}
// Indeterminate state
if ( indeterminate ) {
// Add indeterminate state
node [ state ] = true ;
// Remove checked state
if ( node [ _checked ] ) {
off ( input , _checked , 'force' ) ;
}
// Checked or disabled state
} else {
// Add checked or disabled state
if ( ! keep ) {
node [ state ] = true ;
}
// Remove indeterminate state
if ( checked && node [ _indeterminate ] ) {
off ( input , _indeterminate , false ) ;
}
}
// Trigger callbacks
callbacks ( input , checked , state , keep ) ;
}
// Add proper cursor
if ( node [ _disabled ] && ! ! option ( input , _cursor , true ) ) {
parent . find ( '.' + _iCheckHelper ) . css ( _cursor , 'default' ) ;
}
// Add state class
parent [ _add ] ( specific || option ( input , state ) || '' ) ;
// Set ARIA attribute
if ( ! ! parent . attr ( 'role' ) && ! indeterminate ) {
parent . attr ( 'aria-' + ( disabled ? _disabled : _checked ) , 'true' ) ;
}
// Remove regular state class
parent [ _remove ] ( regular || option ( input , callback ) || '' ) ;
}
// Remove checked, disabled or indeterminate state
function off ( input , state , keep ) {
var node = input [ 0 ] ,
parent = input . parent ( ) ,
checked = state == _checked ,
indeterminate = state == _indeterminate ,
disabled = state == _disabled ,
callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled' ,
regular = option ( input , callback + capitalize ( node [ _type ] ) ) ,
specific = option ( input , state + capitalize ( node [ _type ] ) ) ;
// Prevent unnecessary actions
if ( node [ state ] !== false ) {
// Toggle state
if ( indeterminate || ! keep || keep == 'force' ) {
node [ state ] = false ;
}
// Trigger callbacks
callbacks ( input , checked , callback , keep ) ;
}
// Add proper cursor
if ( ! node [ _disabled ] && ! ! option ( input , _cursor , true ) ) {
parent . find ( '.' + _iCheckHelper ) . css ( _cursor , 'pointer' ) ;
}
// Remove state class
parent [ _remove ] ( specific || option ( input , state ) || '' ) ;
// Set ARIA attribute
if ( ! ! parent . attr ( 'role' ) && ! indeterminate ) {
parent . attr ( 'aria-' + ( disabled ? _disabled : _checked ) , 'false' ) ;
}
// Add regular state class
parent [ _add ] ( regular || option ( input , callback ) || '' ) ;
}
// Remove all traces
function tidy ( input , callback ) {
if ( input . data ( _iCheck ) ) {
// Remove everything except input
input . parent ( ) . html ( input . attr ( 'style' , input . data ( _iCheck ) . s || '' ) ) ;
// Callback
if ( callback ) {
input [ _callback ] ( callback ) ;
}
// Unbind events
input . off ( '.i' ) . unwrap ( ) ;
$ ( _label + '[for="' + input [ 0 ] . id + '"]' ) . add ( input . closest ( _label ) ) . off ( '.i' ) ;
}
}
// Get some option
function option ( input , state , regular ) {
if ( input . data ( _iCheck ) ) {
return input . data ( _iCheck ) . o [ state + ( regular ? '' : 'Class' ) ] ;
}
}
// Capitalize some string
function capitalize ( string ) {
return string . charAt ( 0 ) . toUpperCase ( ) + string . slice ( 1 ) ;
}
// Executable handlers
function callbacks ( input , checked , callback , keep ) {
if ( ! keep ) {
if ( checked ) {
input [ _callback ] ( 'ifToggled' ) ;
}
input [ _callback ] ( 'ifChanged' ) [ _callback ] ( 'if' + capitalize ( callback ) ) ;
}
}
} ) ( window . jQuery || window . Zepto ) ;
/ * !
* Lightbox for Bootstrap by @ ashleydw
* https : //github.com/ashleydw/lightbox
*
* License : https : //github.com/ashleydw/lightbox/blob/master/LICENSE
* /
+ function ( $ ) {
'use strict' ;
var _createClass = ( function ( ) { function defineProperties ( target , props ) { for ( var i = 0 ; i < props . length ; i ++ ) { var descriptor = props [ i ] ; descriptor . enumerable = descriptor . enumerable || false ; descriptor . configurable = true ; if ( 'value' in descriptor ) descriptor . writable = true ; Object . defineProperty ( target , descriptor . key , descriptor ) ; } } return function ( Constructor , protoProps , staticProps ) { if ( protoProps ) defineProperties ( Constructor . prototype , protoProps ) ; if ( staticProps ) defineProperties ( Constructor , staticProps ) ; return Constructor ; } ; } ) ( ) ;
function _classCallCheck ( instance , Constructor ) { if ( ! ( instance instanceof Constructor ) ) { throw new TypeError ( 'Cannot call a class as a function' ) ; } }
var Lightbox = ( function ( $ ) {
var NAME = 'ekkoLightbox' ;
var JQUERY _NO _CONFLICT = $ . fn [ NAME ] ;
var Default = {
title : '' ,
footer : '' ,
maxWidth : 9999 ,
maxHeight : 9999 ,
showArrows : true , //display the left / right arrows or not
wrapping : true , //if true, gallery loops infinitely
type : null , //force the lightbox into image / youtube mode. if null, or not image|youtube|vimeo; detect it
alwaysShowClose : false , //always show the close button, even if there is no title
loadingMessage : '<div class="ekko-lightbox-loader"><div><div></div><div></div></div></div>' , // http://tobiasahlin.com/spinkit/
leftArrow : '<span>❮</span>' ,
rightArrow : '<span>❯</span>' ,
strings : {
close : 'Close' ,
fail : 'Failed to load image:' ,
type : 'Could not detect remote target type. Force the type using data-type'
} ,
doc : document , // if in an iframe can specify top.document
onShow : function onShow ( ) { } ,
onShown : function onShown ( ) { } ,
onHide : function onHide ( ) { } ,
onHidden : function onHidden ( ) { } ,
onNavigate : function onNavigate ( ) { } ,
onContentLoaded : function onContentLoaded ( ) { }
} ;
var Lightbox = ( function ( ) {
_createClass ( Lightbox , null , [ {
key : 'Default' ,
/ * *
Class properties :
_$element : null - > the < a > element currently being displayed
_$modal : The bootstrap modal generated
_$modalDialog : The . modal - dialog
_$modalContent : The . modal - content
_$modalBody : The . modal - body
_$modalHeader : The . modal - header
_$modalFooter : The . modal - footer
_$lightboxContainerOne : Container of the first lightbox element
_$lightboxContainerTwo : Container of the second lightbox element
_$lightboxBody : First element in the container
_$modalArrows : The overlayed arrows container
_$galleryItems : Other < a > ' s available for this gallery
_galleryName : Name of the current data ( 'gallery' ) showing
_galleryIndex : The current index of the _$galleryItems being shown
_config : { } the options for the modal
_modalId : unique id for the current lightbox
_padding / _border : CSS properties for the modal container ; these are used to calculate the available space for the content
* /
get : function get ( ) {
return Default ;
}
} ] ) ;
function Lightbox ( $element , config ) {
var _this = this ;
_classCallCheck ( this , Lightbox ) ;
this . _config = $ . extend ( { } , Default , config ) ;
this . _$modalArrows = null ;
this . _galleryIndex = 0 ;
this . _galleryName = null ;
this . _padding = null ;
this . _border = null ;
this . _titleIsShown = false ;
this . _footerIsShown = false ;
this . _wantedWidth = 0 ;
this . _wantedHeight = 0 ;
this . _touchstartX = 0 ;
this . _touchendX = 0 ;
this . _modalId = 'ekkoLightbox-' + Math . floor ( Math . random ( ) * 1000 + 1 ) ;
this . _$element = $element instanceof jQuery ? $element : $ ( $element ) ;
this . _isBootstrap3 = $ . fn . modal . Constructor . VERSION [ 0 ] == 3 ;
var h4 = '<h4 class="modal-title">' + ( this . _config . title || " " ) + '</h4>' ;
var btn = '<button type="button" class="close" data-dismiss="modal" aria-label="' + this . _config . strings . close + '"><span aria-hidden="true">×</span></button>' ;
var header = '<div class="modal-header' + ( this . _config . title || this . _config . alwaysShowClose ? '' : ' hide' ) + '">' + ( this . _isBootstrap3 ? btn + h4 : h4 + btn ) + '</div>' ;
var footer = '<div class="modal-footer' + ( this . _config . footer ? '' : ' hide' ) + '">' + ( this . _config . footer || " " ) + '</div>' ;
var body = '<div class="modal-body"><div class="ekko-lightbox-container"><div class="ekko-lightbox-item fade in show"></div><div class="ekko-lightbox-item fade"></div></div></div>' ;
var dialog = '<div class="modal-dialog" role="document"><div class="modal-content">' + header + body + footer + '</div></div>' ;
$ ( this . _config . doc . body ) . append ( '<div id="' + this . _modalId + '" class="ekko-lightbox modal fade" tabindex="-1" tabindex="-1" role="dialog" aria-hidden="true">' + dialog + '</div>' ) ;
this . _$modal = $ ( '#' + this . _modalId , this . _config . doc ) ;
this . _$modalDialog = this . _$modal . find ( '.modal-dialog' ) . first ( ) ;
this . _$modalContent = this . _$modal . find ( '.modal-content' ) . first ( ) ;
this . _$modalBody = this . _$modal . find ( '.modal-body' ) . first ( ) ;
this . _$modalHeader = this . _$modal . find ( '.modal-header' ) . first ( ) ;
this . _$modalFooter = this . _$modal . find ( '.modal-footer' ) . first ( ) ;
this . _$lightboxContainer = this . _$modalBody . find ( '.ekko-lightbox-container' ) . first ( ) ;
this . _$lightboxBodyOne = this . _$lightboxContainer . find ( '> div:first-child' ) . first ( ) ;
this . _$lightboxBodyTwo = this . _$lightboxContainer . find ( '> div:last-child' ) . first ( ) ;
this . _border = this . _calculateBorders ( ) ;
this . _padding = this . _calculatePadding ( ) ;
this . _galleryName = this . _$element . data ( 'gallery' ) ;
if ( this . _galleryName ) {
this . _$galleryItems = $ ( document . body ) . find ( '*[data-gallery="' + this . _galleryName + '"]' ) ;
this . _galleryIndex = this . _$galleryItems . index ( this . _$element ) ;
$ ( document ) . on ( 'keydown.ekkoLightbox' , this . _navigationalBinder . bind ( this ) ) ;
// add the directional arrows to the modal
if ( this . _config . showArrows && this . _$galleryItems . length > 1 ) {
this . _$lightboxContainer . append ( '<div class="ekko-lightbox-nav-overlay"><a href="#">' + this . _config . leftArrow + '</a><a href="#">' + this . _config . rightArrow + '</a></div>' ) ;
this . _$modalArrows = this . _$lightboxContainer . find ( 'div.ekko-lightbox-nav-overlay' ) . first ( ) ;
this . _$lightboxContainer . on ( 'click' , 'a:first-child' , function ( event ) {
event . preventDefault ( ) ;
return _this . navigateLeft ( ) ;
} ) ;
this . _$lightboxContainer . on ( 'click' , 'a:last-child' , function ( event ) {
event . preventDefault ( ) ;
return _this . navigateRight ( ) ;
} ) ;
this . updateNavigation ( ) ;
}
}
this . _$modal . on ( 'show.bs.modal' , this . _config . onShow . bind ( this ) ) . on ( 'shown.bs.modal' , function ( ) {
_this . _toggleLoading ( true ) ;
_this . _handle ( ) ;
return _this . _config . onShown . call ( _this ) ;
} ) . on ( 'hide.bs.modal' , this . _config . onHide . bind ( this ) ) . on ( 'hidden.bs.modal' , function ( ) {
if ( _this . _galleryName ) {
$ ( document ) . off ( 'keydown.ekkoLightbox' ) ;
$ ( window ) . off ( 'resize.ekkoLightbox' ) ;
}
_this . _$modal . remove ( ) ;
return _this . _config . onHidden . call ( _this ) ;
} ) . modal ( this . _config ) ;
$ ( window ) . on ( 'resize.ekkoLightbox' , function ( ) {
_this . _resize ( _this . _wantedWidth , _this . _wantedHeight ) ;
} ) ;
this . _$lightboxContainer . on ( 'touchstart' , function ( ) {
_this . _touchstartX = event . changedTouches [ 0 ] . screenX ;
} ) . on ( 'touchend' , function ( ) {
_this . _touchendX = event . changedTouches [ 0 ] . screenX ;
_this . _swipeGesure ( ) ;
} ) ;
}
_createClass ( Lightbox , [ {
key : 'element' ,
value : function element ( ) {
return this . _$element ;
}
} , {
key : 'modal' ,
value : function modal ( ) {
return this . _$modal ;
}
} , {
key : 'navigateTo' ,
value : function navigateTo ( index ) {
if ( index < 0 || index > this . _$galleryItems . length - 1 ) return this ;
this . _galleryIndex = index ;
this . updateNavigation ( ) ;
this . _$element = $ ( this . _$galleryItems . get ( this . _galleryIndex ) ) ;
this . _handle ( ) ;
}
} , {
key : 'navigateLeft' ,
value : function navigateLeft ( ) {
if ( ! this . _$galleryItems ) return ;
if ( this . _$galleryItems . length === 1 ) return ;
if ( this . _galleryIndex === 0 ) {
if ( this . _config . wrapping ) this . _galleryIndex = this . _$galleryItems . length - 1 ; else return ;
} else //circular
this . _galleryIndex -- ;
this . _config . onNavigate . call ( this , 'left' , this . _galleryIndex ) ;
return this . navigateTo ( this . _galleryIndex ) ;
}
} , {
key : 'navigateRight' ,
value : function navigateRight ( ) {
if ( ! this . _$galleryItems ) return ;
if ( this . _$galleryItems . length === 1 ) return ;
if ( this . _galleryIndex === this . _$galleryItems . length - 1 ) {
if ( this . _config . wrapping ) this . _galleryIndex = 0 ; else return ;
} else //circular
this . _galleryIndex ++ ;
this . _config . onNavigate . call ( this , 'right' , this . _galleryIndex ) ;
return this . navigateTo ( this . _galleryIndex ) ;
}
} , {
key : 'updateNavigation' ,
value : function updateNavigation ( ) {
if ( ! this . _config . wrapping ) {
var $nav = this . _$lightboxContainer . find ( 'div.ekko-lightbox-nav-overlay' ) ;
if ( this . _galleryIndex === 0 ) $nav . find ( 'a:first-child' ) . addClass ( 'disabled' ) ; else $nav . find ( 'a:first-child' ) . removeClass ( 'disabled' ) ;
if ( this . _galleryIndex === this . _$galleryItems . length - 1 ) $nav . find ( 'a:last-child' ) . addClass ( 'disabled' ) ; else $nav . find ( 'a:last-child' ) . removeClass ( 'disabled' ) ;
}
}
} , {
key : 'close' ,
value : function close ( ) {
return this . _$modal . modal ( 'hide' ) ;
}
// helper private methods
} , {
key : '_navigationalBinder' ,
value : function _navigationalBinder ( event ) {
event = event || window . event ;
if ( event . keyCode === 39 ) return this . navigateRight ( ) ;
if ( event . keyCode === 37 ) return this . navigateLeft ( ) ;
}
// type detection private methods
} , {
key : '_detectRemoteType' ,
value : function _detectRemoteType ( src , type ) {
type = type || false ;
if ( ! type && this . _isImage ( src ) ) type = 'image' ;
if ( ! type && this . _getYoutubeId ( src ) ) type = 'youtube' ;
if ( ! type && this . _getVimeoId ( src ) ) type = 'vimeo' ;
if ( ! type && this . _getInstagramId ( src ) ) type = 'instagram' ;
if ( ! type || [ 'image' , 'youtube' , 'vimeo' , 'instagram' , 'video' , 'url' ] . indexOf ( type ) < 0 ) type = 'url' ;
return type ;
}
} , {
key : '_isImage' ,
value : function _isImage ( string ) {
return string && string . match ( /(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i ) ;
}
} , {
key : '_containerToUse' ,
value : function _containerToUse ( ) {
var _this2 = this ;
// if currently showing an image, fade it out and remove
var $toUse = this . _$lightboxBodyTwo ;
var $current = this . _$lightboxBodyOne ;
if ( this . _$lightboxBodyTwo . hasClass ( 'in' ) ) {
$toUse = this . _$lightboxBodyOne ;
$current = this . _$lightboxBodyTwo ;
}
$current . removeClass ( 'in show' ) ;
setTimeout ( function ( ) {
if ( ! _this2 . _$lightboxBodyTwo . hasClass ( 'in' ) ) _this2 . _$lightboxBodyTwo . empty ( ) ;
if ( ! _this2 . _$lightboxBodyOne . hasClass ( 'in' ) ) _this2 . _$lightboxBodyOne . empty ( ) ;
} , 500 ) ;
$toUse . addClass ( 'in show' ) ;
return $toUse ;
}
} , {
key : '_handle' ,
value : function _handle ( ) {
var $toUse = this . _containerToUse ( ) ;
this . _updateTitleAndFooter ( ) ;
var currentRemote = this . _$element . attr ( 'data-remote' ) || this . _$element . attr ( 'href' ) ;
var currentType = this . _detectRemoteType ( currentRemote , this . _$element . attr ( 'data-type' ) || false ) ;
if ( [ 'image' , 'youtube' , 'vimeo' , 'instagram' , 'video' , 'url' ] . indexOf ( currentType ) < 0 ) return this . _error ( this . _config . strings . type ) ;
switch ( currentType ) {
case 'image' :
this . _preloadImage ( currentRemote , $toUse ) ;
this . _preloadImageByIndex ( this . _galleryIndex , 3 ) ;
break ;
case 'youtube' :
this . _showYoutubeVideo ( currentRemote , $toUse ) ;
break ;
case 'vimeo' :
this . _showVimeoVideo ( this . _getVimeoId ( currentRemote ) , $toUse ) ;
break ;
case 'instagram' :
this . _showInstagramVideo ( this . _getInstagramId ( currentRemote ) , $toUse ) ;
break ;
case 'video' :
this . _showHtml5Video ( currentRemote , $toUse ) ;
break ;
default :
// url
this . _loadRemoteContent ( currentRemote , $toUse ) ;
break ;
}
return this ;
}
} , {
key : '_getYoutubeId' ,
value : function _getYoutubeId ( string ) {
if ( ! string ) return false ;
var matches = string . match ( /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/ ) ;
return matches && matches [ 2 ] . length === 11 ? matches [ 2 ] : false ;
}
} , {
key : '_getVimeoId' ,
value : function _getVimeoId ( string ) {
return string && string . indexOf ( 'vimeo' ) > 0 ? string : false ;
}
} , {
key : '_getInstagramId' ,
value : function _getInstagramId ( string ) {
return string && string . indexOf ( 'instagram' ) > 0 ? string : false ;
}
// layout private methods
} , {
key : '_toggleLoading' ,
value : function _toggleLoading ( show ) {
show = show || false ;
if ( show ) {
this . _$modalDialog . css ( 'display' , 'none' ) ;
this . _$modal . removeClass ( 'in show' ) ;
$ ( '.modal-backdrop' ) . append ( this . _config . loadingMessage ) ;
} else {
this . _$modalDialog . css ( 'display' , 'block' ) ;
this . _$modal . addClass ( 'in show' ) ;
$ ( '.modal-backdrop' ) . find ( '.ekko-lightbox-loader' ) . remove ( ) ;
}
return this ;
}
} , {
key : '_calculateBorders' ,
value : function _calculateBorders ( ) {
return {
top : this . _totalCssByAttribute ( 'border-top-width' ) ,
right : this . _totalCssByAttribute ( 'border-right-width' ) ,
bottom : this . _totalCssByAttribute ( 'border-bottom-width' ) ,
left : this . _totalCssByAttribute ( 'border-left-width' )
} ;
}
} , {
key : '_calculatePadding' ,
value : function _calculatePadding ( ) {
return {
top : this . _totalCssByAttribute ( 'padding-top' ) ,
right : this . _totalCssByAttribute ( 'padding-right' ) ,
bottom : this . _totalCssByAttribute ( 'padding-bottom' ) ,
left : this . _totalCssByAttribute ( 'padding-left' )
} ;
}
} , {
key : '_totalCssByAttribute' ,
value : function _totalCssByAttribute ( attribute ) {
return parseInt ( this . _$modalDialog . css ( attribute ) , 10 ) + parseInt ( this . _$modalContent . css ( attribute ) , 10 ) + parseInt ( this . _$modalBody . css ( attribute ) , 10 ) ;
}
} , {
key : '_updateTitleAndFooter' ,
value : function _updateTitleAndFooter ( ) {
var title = this . _$element . data ( 'title' ) || "" ;
var caption = this . _$element . data ( 'footer' ) || "" ;
this . _titleIsShown = false ;
if ( title || this . _config . alwaysShowClose ) {
this . _titleIsShown = true ;
this . _$modalHeader . css ( 'display' , '' ) . find ( '.modal-title' ) . html ( title || " " ) ;
} else this . _$modalHeader . css ( 'display' , 'none' ) ;
this . _footerIsShown = false ;
if ( caption ) {
this . _footerIsShown = true ;
this . _$modalFooter . css ( 'display' , '' ) . html ( caption ) ;
} else this . _$modalFooter . css ( 'display' , 'none' ) ;
return this ;
}
} , {
key : '_showYoutubeVideo' ,
value : function _showYoutubeVideo ( remote , $containerForElement ) {
var id = this . _getYoutubeId ( remote ) ;
var query = remote . indexOf ( '&' ) > 0 ? remote . substr ( remote . indexOf ( '&' ) ) : '' ;
var width = this . _$element . data ( 'width' ) || 560 ;
var height = this . _$element . data ( 'height' ) || width / ( 560 / 315 ) ;
return this . _showVideoIframe ( '//www.youtube.com/embed/' + id + '?badge=0&autoplay=1&html5=1' + query , width , height , $containerForElement ) ;
}
} , {
key : '_showVimeoVideo' ,
value : function _showVimeoVideo ( id , $containerForElement ) {
var width = this . _$element . data ( 'width' ) || 500 ;
var height = this . _$element . data ( 'height' ) || width / ( 560 / 315 ) ;
return this . _showVideoIframe ( id + '?autoplay=1' , width , height , $containerForElement ) ;
}
} , {
key : '_showInstagramVideo' ,
value : function _showInstagramVideo ( id , $containerForElement ) {
// instagram load their content into iframe's so this can be put straight into the element
var width = this . _$element . data ( 'width' ) || 612 ;
var height = width + 80 ;
id = id . substr ( - 1 ) !== '/' ? id + '/' : id ; // ensure id has trailing slash
$containerForElement . html ( '<iframe width="' + width + '" height="' + height + '" src="' + id + 'embed/" frameborder="0" allowfullscreen></iframe>' ) ;
this . _resize ( width , height ) ;
this . _config . onContentLoaded . call ( this ) ;
if ( this . _$modalArrows ) //hide the arrows when showing video
this . _$modalArrows . css ( 'display' , 'none' ) ;
this . _toggleLoading ( false ) ;
return this ;
}
} , {
key : '_showVideoIframe' ,
value : function _showVideoIframe ( url , width , height , $containerForElement ) {
// should be used for videos only. for remote content use loadRemoteContent (data-type=url)
height = height || width ; // default to square
$containerForElement . html ( '<div class="embed-responsive embed-responsive-16by9"><iframe width="' + width + '" height="' + height + '" src="' + url + '" frameborder="0" allowfullscreen class="embed-responsive-item"></iframe></div>' ) ;
this . _resize ( width , height ) ;
this . _config . onContentLoaded . call ( this ) ;
if ( this . _$modalArrows ) this . _$modalArrows . css ( 'display' , 'none' ) ; //hide the arrows when showing video
this . _toggleLoading ( false ) ;
return this ;
}
} , {
key : '_showHtml5Video' ,
value : function _showHtml5Video ( url , $containerForElement ) {
// should be used for videos only. for remote content use loadRemoteContent (data-type=url)
var width = this . _$element . data ( 'width' ) || 560 ;
var height = this . _$element . data ( 'height' ) || width / ( 560 / 315 ) ;
$containerForElement . html ( '<div class="embed-responsive embed-responsive-16by9"><video width="' + width + '" height="' + height + '" src="' + url + '" preload="auto" autoplay controls class="embed-responsive-item"></video></div>' ) ;
this . _resize ( width , height ) ;
this . _config . onContentLoaded . call ( this ) ;
if ( this . _$modalArrows ) this . _$modalArrows . css ( 'display' , 'none' ) ; //hide the arrows when showing video
this . _toggleLoading ( false ) ;
return this ;
}
} , {
key : '_loadRemoteContent' ,
value : function _loadRemoteContent ( url , $containerForElement ) {
var _this3 = this ;
var width = this . _$element . data ( 'width' ) || 560 ;
var height = this . _$element . data ( 'height' ) || 560 ;
var disableExternalCheck = this . _$element . data ( 'disableExternalCheck' ) || false ;
this . _toggleLoading ( false ) ;
// external urls are loading into an iframe
// local ajax can be loaded into the container itself
if ( ! disableExternalCheck && ! this . _isExternal ( url ) ) {
$containerForElement . load ( url , $ . proxy ( function ( ) {
return _this3 . _$element . trigger ( 'loaded.bs.modal' ) ; l ;
} ) ) ;
} else {
$containerForElement . html ( '<iframe src="' + url + '" frameborder="0" allowfullscreen></iframe>' ) ;
this . _config . onContentLoaded . call ( this ) ;
}
if ( this . _$modalArrows ) //hide the arrows when remote content
this . _$modalArrows . css ( 'display' , 'none' ) ;
this . _resize ( width , height ) ;
return this ;
}
} , {
key : '_isExternal' ,
value : function _isExternal ( url ) {
var match = url . match ( /^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/ ) ;
if ( typeof match [ 1 ] === "string" && match [ 1 ] . length > 0 && match [ 1 ] . toLowerCase ( ) !== location . protocol ) return true ;
if ( typeof match [ 2 ] === "string" && match [ 2 ] . length > 0 && match [ 2 ] . replace ( new RegExp ( ':(' + ( {
"http:" : 80 ,
"https:" : 443
} ) [ location . protocol ] + ')?$' ) , "" ) !== location . host ) return true ;
return false ;
}
} , {
key : '_error' ,
value : function _error ( message ) {
console . error ( message ) ;
this . _containerToUse ( ) . html ( message ) ;
this . _resize ( 300 , 300 ) ;
return this ;
}
} , {
key : '_preloadImageByIndex' ,
value : function _preloadImageByIndex ( startIndex , numberOfTimes ) {
if ( ! this . _$galleryItems ) return ;
var next = $ ( this . _$galleryItems . get ( startIndex ) , false ) ;
if ( typeof next == 'undefined' ) return ;
var src = next . attr ( 'data-remote' ) || next . attr ( 'href' ) ;
if ( next . attr ( 'data-type' ) === 'image' || this . _isImage ( src ) ) this . _preloadImage ( src , false ) ;
if ( numberOfTimes > 0 ) return this . _preloadImageByIndex ( startIndex + 1 , numberOfTimes - 1 ) ;
}
} , {
key : '_preloadImage' ,
value : function _preloadImage ( src , $containerForImage ) {
var _this4 = this ;
$containerForImage = $containerForImage || false ;
var img = new Image ( ) ;
if ( $containerForImage ) {
( function ( ) {
// if loading takes > 200ms show a loader
var loadingTimeout = setTimeout ( function ( ) {
$containerForImage . append ( _this4 . _config . loadingMessage ) ;
} , 200 ) ;
img . onload = function ( ) {
if ( loadingTimeout ) clearTimeout ( loadingTimeout ) ;
loadingTimeout = null ;
var image = $ ( '<img />' ) ;
image . attr ( 'src' , img . src ) ;
image . addClass ( 'img-fluid' ) ;
// backward compatibility for bootstrap v3
image . css ( 'width' , '100%' ) ;
$containerForImage . html ( image ) ;
if ( _this4 . _$modalArrows ) _this4 . _$modalArrows . css ( 'display' , '' ) ; // remove display to default to css property
_this4 . _resize ( img . width , img . height ) ;
_this4 . _toggleLoading ( false ) ;
return _this4 . _config . onContentLoaded . call ( _this4 ) ;
} ;
img . onerror = function ( ) {
_this4 . _toggleLoading ( false ) ;
return _this4 . _error ( _this4 . _config . strings . fail + ( ' ' + src ) ) ;
} ;
} ) ( ) ;
}
img . src = src ;
return img ;
}
} , {
key : '_swipeGesure' ,
value : function _swipeGesure ( ) {
if ( this . _touchendX < this . _touchstartX ) {
return this . navigateRight ( ) ;
}
if ( this . _touchendX > this . _touchstartX ) {
return this . navigateLeft ( ) ;
}
}
} , {
key : '_resize' ,
value : function _resize ( width , height ) {
height = height || width ;
this . _wantedWidth = width ;
this . _wantedHeight = height ;
var imageAspecRatio = width / height ;
// if width > the available space, scale down the expected width and height
var widthBorderAndPadding = this . _padding . left + this . _padding . right + this . _border . left + this . _border . right ;
// force 10px margin if window size > 575px
var addMargin = this . _config . doc . body . clientWidth > 575 ? 20 : 0 ;
var discountMargin = this . _config . doc . body . clientWidth > 575 ? 0 : 20 ;
var maxWidth = Math . min ( width + widthBorderAndPadding , this . _config . doc . body . clientWidth - addMargin , this . _config . maxWidth ) ;
if ( width + widthBorderAndPadding > maxWidth ) {
height = ( maxWidth - widthBorderAndPadding - discountMargin ) / imageAspecRatio ;
width = maxWidth ;
} else width = width + widthBorderAndPadding ;
var headerHeight = 0 ,
footerHeight = 0 ;
// as the resize is performed the modal is show, the calculate might fail
// if so, default to the default sizes
if ( this . _footerIsShown ) footerHeight = this . _$modalFooter . outerHeight ( true ) || 55 ;
if ( this . _titleIsShown ) headerHeight = this . _$modalHeader . outerHeight ( true ) || 67 ;
var borderPadding = this . _padding . top + this . _padding . bottom + this . _border . bottom + this . _border . top ;
//calculated each time as resizing the window can cause them to change due to Bootstraps fluid margins
var margins = parseFloat ( this . _$modalDialog . css ( 'margin-top' ) ) + parseFloat ( this . _$modalDialog . css ( 'margin-bottom' ) ) ;
var maxHeight = Math . min ( height , $ ( window ) . height ( ) - borderPadding - margins - headerHeight - footerHeight , this . _config . maxHeight - borderPadding - headerHeight - footerHeight ) ;
if ( height > maxHeight ) {
// if height > the available height, scale down the width
width = Math . ceil ( maxHeight * imageAspecRatio ) + widthBorderAndPadding ;
}
this . _$lightboxContainer . css ( 'height' , maxHeight ) ;
this . _$modalDialog . css ( 'flex' , 1 ) . css ( 'maxWidth' , width ) ;
var modal = this . _$modal . data ( 'bs.modal' ) ;
if ( modal ) {
// v4 method is mistakenly protected
try {
modal . _handleUpdate ( ) ;
} catch ( Exception ) {
modal . handleUpdate ( ) ;
}
}
return this ;
}
} ] , [ {
key : '_jQueryInterface' ,
value : function _jQueryInterface ( config ) {
var _this5 = this ;
config = config || { } ;
return this . each ( function ( ) {
var $this = $ ( _this5 ) ;
var _config = $ . extend ( { } , Lightbox . Default , $this . data ( ) , typeof config === 'object' && config ) ;
new Lightbox ( _this5 , _config ) ;
} ) ;
}
} ] ) ;
return Lightbox ;
} ) ( ) ;
$ . fn [ NAME ] = Lightbox . _jQueryInterface ;
$ . fn [ NAME ] . Constructor = Lightbox ;
$ . fn [ NAME ] . noConflict = function ( ) {
$ . fn [ NAME ] = JQUERY _NO _CONFLICT ;
return Lightbox . _jQueryInterface ;
} ;
return Lightbox ;
} ) ( jQuery ) ;
//# sourceMappingURL=ekko-lightbox.js.map
} ( jQuery ) ;
/ * ! A d m i n L T E a p p . j s
* === === === === === =
* Main JS application file for AdminLTE v2 . This file
* should be included in all pages . It controls some layout
* options and implements exclusive AdminLTE plugins .
*
* @ Author Almsaeed Studio
* @ Support < http : //www.almsaeedstudio.com>
* @ Email < support @ almsaeedstudio . com >
* @ version 2.3 . 0
* @ license MIT < http : //opensource.org/licenses/MIT>
* /
//Make sure jQuery has been loaded before app.js
if ( typeof jQuery === "undefined" ) {
throw new Error ( "AdminLTE requires jQuery" ) ;
}
/ * A d m i n L T E
*
* @ type Object
* @ description $ . AdminLTE is the main object for the template ' s app .
* It ' s used for implementing functions and options related
* to the template . Keeping everything wrapped in an object
* prevents conflict with other plugins and is a better
* way to organize our code .
* /
$ . AdminLTE = { } ;
/ * - - - - - - - - - - - - - - - - - - - -
* - AdminLTE Options -
* -- -- -- -- -- -- -- -- -- --
* Modify these options to suit your implementation
* /
$ . AdminLTE . options = {
//Add slimscroll to navbar menus
//This requires you to load the slimscroll plugin
//in every page before app.js
navbarMenuSlimscroll : true ,
navbarMenuSlimscrollWidth : "3px" , //The width of the scroll bar
navbarMenuHeight : "200px" , //The height of the inner menu
//General animation speed for JS animated elements such as box collapse/expand and
//sidebar treeview slide up/down. This options accepts an integer as milliseconds,
//'fast', 'normal', or 'slow'
animationSpeed : 500 ,
//Sidebar push menu toggle button selector
sidebarToggleSelector : "[data-toggle='offcanvas']" ,
//Activate sidebar push menu
sidebarPushMenu : true ,
//Activate sidebar slimscroll if the fixed layout is set (requires SlimScroll Plugin)
sidebarSlimScroll : true ,
//Enable sidebar expand on hover effect for sidebar mini
//This option is forced to true if both the fixed layout and sidebar mini
//are used together
sidebarExpandOnHover : false ,
//BoxRefresh Plugin
enableBoxRefresh : true ,
//Bootstrap.js tooltip
enableBSToppltip : true ,
BSTooltipSelector : "[data-toggle='tooltip']" ,
//Enable Fast Click. Fastclick.js creates a more
//native touch experience with touch devices. If you
//choose to enable the plugin, make sure you load the script
//before AdminLTE's app.js
enableFastclick : false ,
//Control Sidebar Options
enableControlSidebar : true ,
controlSidebarOptions : {
//Which button should trigger the open/close event
toggleBtnSelector : "[data-toggle='control-sidebar']" ,
//The sidebar selector
selector : ".control-sidebar" ,
//Enable slide over content
slide : true
} ,
//Box Widget Plugin. Enable this plugin
//to allow boxes to be collapsed and/or removed
enableBoxWidget : true ,
//Box Widget plugin options
boxWidgetOptions : {
boxWidgetIcons : {
//Collapse icon
collapse : 'fa-minus' ,
//Open icon
open : 'fa-plus' ,
//Remove icon
remove : 'fa-times'
} ,
boxWidgetSelectors : {
//Remove button selector
remove : '[data-widget="remove"]' ,
//Collapse button selector
collapse : '[data-widget="collapse"]'
}
} ,
//Direct Chat plugin options
directChat : {
//Enable direct chat by default
enable : true ,
//The button to open and close the chat contacts pane
contactToggleSelector : '[data-widget="chat-pane-toggle"]'
} ,
//Define the set of colors to use globally around the website
colors : {
lightBlue : "#3c8dbc" ,
red : "#f56954" ,
green : "#00a65a" ,
aqua : "#00c0ef" ,
yellow : "#f39c12" ,
blue : "#0073b7" ,
navy : "#001F3F" ,
teal : "#39CCCC" ,
olive : "#3D9970" ,
lime : "#01FF70" ,
orange : "#FF851B" ,
fuchsia : "#F012BE" ,
purple : "#8E24AA" ,
maroon : "#D81B60" ,
black : "#222222" ,
gray : "#d2d6de"
} ,
//The standard screen sizes that bootstrap uses.
//If you change these in the variables.less file, change
//them here too.
screenSizes : {
xs : 480 ,
sm : 768 ,
md : 992 ,
lg : 1200
}
} ;
/ * - - - - - - - - - - - - - - - - - -
* - Implementation -
* -- -- -- -- -- -- -- -- --
* The next block of code implements AdminLTE ' s
* functions and plugins as specified by the
* options above .
* /
$ ( function ( ) {
"use strict" ;
//Fix for IE page transitions
$ ( "body" ) . removeClass ( "hold-transition" ) ;
//Extend options if external options exist
if ( typeof AdminLTEOptions !== "undefined" ) {
$ . extend ( true ,
$ . AdminLTE . options ,
AdminLTEOptions ) ;
}
//Easy access to options
var o = $ . AdminLTE . options ;
//Set up the object
_init ( ) ;
//Activate the layout maker
$ . AdminLTE . layout . activate ( ) ;
//Enable sidebar tree view controls
$ . AdminLTE . tree ( '.sidebar' ) ;
//Enable control sidebar
if ( o . enableControlSidebar ) {
$ . AdminLTE . controlSidebar . activate ( ) ;
}
//Add slimscroll to navbar dropdown
if ( o . navbarMenuSlimscroll && typeof $ . fn . slimscroll != 'undefined' ) {
$ ( ".navbar .menu" ) . slimscroll ( {
height : o . navbarMenuHeight ,
alwaysVisible : false ,
size : o . navbarMenuSlimscrollWidth
} ) . css ( "width" , "100%" ) ;
}
//Activate sidebar push menu
if ( o . sidebarPushMenu ) {
$ . AdminLTE . pushMenu . activate ( o . sidebarToggleSelector ) ;
}
//Activate Bootstrap tooltip
if ( o . enableBSToppltip ) {
$ . widget . bridge ( 'uitooltip' , $ . ui . tooltip ) ;
$ ( 'body' ) . tooltip ( {
selector : o . BSTooltipSelector
} ) ;
}
//Activate box widget
if ( o . enableBoxWidget ) {
$ . AdminLTE . boxWidget . activate ( ) ;
}
//Activate fast click
if ( o . enableFastclick && typeof FastClick != 'undefined' ) {
FastClick . attach ( document . body ) ;
}
//Activate direct chat widget
if ( o . directChat . enable ) {
$ ( document ) . on ( 'click' , o . directChat . contactToggleSelector , function ( ) {
var box = $ ( this ) . parents ( '.direct-chat' ) . first ( ) ;
box . toggleClass ( 'direct-chat-contacts-open' ) ;
} ) ;
}
/ *
* INITIALIZE BUTTON TOGGLE
* -- -- -- -- -- -- -- -- -- -- -- --
* /
$ ( '.btn-group[data-toggle="btn-toggle"]' ) . each ( function ( ) {
var group = $ ( this ) ;
$ ( this ) . find ( ".btn" ) . on ( 'click' , function ( e ) {
group . find ( ".btn.active" ) . removeClass ( "active" ) ;
$ ( this ) . addClass ( "active" ) ;
e . preventDefault ( ) ;
} ) ;
} ) ;
} ) ;
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - Initialize the AdminLTE Object -
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* All AdminLTE functions are implemented below .
* /
function _init ( ) {
'use strict' ;
/ * L a y o u t
* === ===
* Fixes the layout height in case min - height fails .
*
* @ type Object
* @ usage $ . AdminLTE . layout . activate ( )
* $ . AdminLTE . layout . fix ( )
* $ . AdminLTE . layout . fixSidebar ( )
* /
$ . AdminLTE . layout = {
activate : function ( ) {
var _this = this ;
_this . fix ( ) ;
_this . fixSidebar ( ) ;
$ ( window , ".wrapper" ) . resize ( function ( ) {
_this . fix ( ) ;
_this . fixSidebar ( ) ;
} ) ;
} ,
fix : function ( ) {
//Get window height and the wrapper height
var neg = $ ( '.main-header' ) . outerHeight ( ) + $ ( '.main-footer' ) . outerHeight ( ) ;
var window _height = $ ( window ) . height ( ) ;
var sidebar _height = $ ( ".sidebar" ) . height ( ) ;
//Set the min-height of the content and sidebar based on the
//the height of the document.
if ( $ ( "body" ) . hasClass ( "fixed" ) ) {
$ ( ".content-wrapper, .right-side" ) . css ( 'min-height' , window _height - $ ( '.main-footer' ) . outerHeight ( ) ) ;
} else {
var postSetWidth ;
if ( window _height >= sidebar _height ) {
$ ( ".content-wrapper, .right-side" ) . css ( 'min-height' , window _height - neg ) ;
postSetWidth = window _height - neg ;
} else {
$ ( ".content-wrapper, .right-side" ) . css ( 'min-height' , sidebar _height ) ;
postSetWidth = sidebar _height ;
}
//Fix for the control sidebar height
var controlSidebar = $ ( $ . AdminLTE . options . controlSidebarOptions . selector ) ;
if ( typeof controlSidebar !== "undefined" ) {
if ( controlSidebar . height ( ) > postSetWidth )
$ ( ".content-wrapper, .right-side" ) . css ( 'min-height' , controlSidebar . height ( ) ) ;
}
}
} ,
fixSidebar : function ( ) {
//Make sure the body tag has the .fixed class
if ( ! $ ( "body" ) . hasClass ( "fixed" ) ) {
if ( typeof $ . fn . slimScroll != 'undefined' ) {
$ ( ".sidebar" ) . slimScroll ( { destroy : true } ) . height ( "auto" ) ;
}
return ;
} else if ( typeof $ . fn . slimScroll == 'undefined' && window . console ) {
window . console . error ( "Error: the fixed layout requires the slimscroll plugin!" ) ;
}
//Enable slimscroll for fixed layout
if ( $ . AdminLTE . options . sidebarSlimScroll ) {
if ( typeof $ . fn . slimScroll != 'undefined' ) {
//Destroy if it exists
$ ( ".sidebar" ) . slimScroll ( { destroy : true } ) . height ( "auto" ) ;
//Add slimscroll
$ ( ".sidebar" ) . slimscroll ( {
height : ( $ ( window ) . height ( ) - $ ( ".main-header" ) . height ( ) ) + "px" ,
color : "rgba(0,0,0,0.2)" ,
size : "3px"
} ) ;
}
}
}
} ;
/ * P u s h M e n u ( )
* === === === =
* Adds the push menu functionality to the sidebar .
*
* @ type Function
* @ usage : $ . AdminLTE . pushMenu ( "[data-toggle='offcanvas']" )
* /
$ . AdminLTE . pushMenu = {
activate : function ( toggleBtn ) {
//Get the screen sizes
var screenSizes = $ . AdminLTE . options . screenSizes ;
//Enable sidebar toggle
$ ( toggleBtn ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
//Enable sidebar push menu
if ( $ ( window ) . width ( ) > ( screenSizes . sm - 1 ) ) {
if ( $ ( "body" ) . hasClass ( 'sidebar-collapse' ) ) {
$ ( "body" ) . removeClass ( 'sidebar-collapse' ) . trigger ( 'expanded.pushMenu' ) ;
} else {
$ ( "body" ) . addClass ( 'sidebar-collapse' ) . trigger ( 'collapsed.pushMenu' ) ;
}
}
//Handle sidebar push menu for small screens
else {
if ( $ ( "body" ) . hasClass ( 'sidebar-open' ) ) {
$ ( "body" ) . removeClass ( 'sidebar-open' ) . removeClass ( 'sidebar-collapse' ) . trigger ( 'collapsed.pushMenu' ) ;
} else {
$ ( "body" ) . addClass ( 'sidebar-open' ) . trigger ( 'expanded.pushMenu' ) ;
}
}
} ) ;
$ ( ".content-wrapper" ) . click ( function ( ) {
//Enable hide menu when clicking on the content-wrapper on small screens
if ( $ ( window ) . width ( ) <= ( screenSizes . sm - 1 ) && $ ( "body" ) . hasClass ( "sidebar-open" ) ) {
$ ( "body" ) . removeClass ( 'sidebar-open' ) ;
}
} ) ;
//Enable expand on hover for sidebar mini
if ( $ . AdminLTE . options . sidebarExpandOnHover
|| ( $ ( 'body' ) . hasClass ( 'fixed' )
&& $ ( 'body' ) . hasClass ( 'sidebar-mini' ) ) ) {
this . expandOnHover ( ) ;
}
} ,
expandOnHover : function ( ) {
var _this = this ;
var screenWidth = $ . AdminLTE . options . screenSizes . sm - 1 ;
//Expand sidebar on hover
$ ( '.main-sidebar' ) . hover ( function ( ) {
if ( $ ( 'body' ) . hasClass ( 'sidebar-mini' )
&& $ ( "body" ) . hasClass ( 'sidebar-collapse' )
&& $ ( window ) . width ( ) > screenWidth ) {
_this . expand ( ) ;
}
} , function ( ) {
if ( $ ( 'body' ) . hasClass ( 'sidebar-mini' )
&& $ ( 'body' ) . hasClass ( 'sidebar-expanded-on-hover' )
&& $ ( window ) . width ( ) > screenWidth ) {
_this . collapse ( ) ;
}
} ) ;
} ,
expand : function ( ) {
$ ( "body" ) . removeClass ( 'sidebar-collapse' ) . addClass ( 'sidebar-expanded-on-hover' ) ;
} ,
collapse : function ( ) {
if ( $ ( 'body' ) . hasClass ( 'sidebar-expanded-on-hover' ) ) {
$ ( 'body' ) . removeClass ( 'sidebar-expanded-on-hover' ) . addClass ( 'sidebar-collapse' ) ;
}
}
} ;
/ * T r e e ( )
* === ===
* Converts the sidebar into a multilevel
* tree view menu .
*
* @ type Function
* @ Usage : $ . AdminLTE . tree ( '.sidebar' )
* /
$ . AdminLTE . tree = function ( menu ) {
var _this = this ;
var animationSpeed = $ . AdminLTE . options . animationSpeed ;
$ ( document ) . on ( 'click' , menu + ' li a' , function ( e ) {
//Get the clicked link and the next element
var $this = $ ( this ) ;
var checkElement = $this . next ( ) ;
//Check if the next element is a menu and is visible
if ( ( checkElement . is ( '.treeview-menu' ) ) && ( checkElement . is ( ':visible' ) ) ) {
//Close the menu
checkElement . slideUp ( animationSpeed , function ( ) {
checkElement . removeClass ( 'menu-open' ) ;
//Fix the layout in case the sidebar stretches over the height of the window
//_this.layout.fix();
} ) ;
checkElement . parent ( "li" ) . removeClass ( "active" ) ;
}
//If the menu is not visible
else if ( ( checkElement . is ( '.treeview-menu' ) ) && ( ! checkElement . is ( ':visible' ) ) ) {
//Get the parent menu
var parent = $this . parents ( 'ul' ) . first ( ) ;
//Close all open menus within the parent
var ul = parent . find ( 'ul:visible' ) . slideUp ( animationSpeed ) ;
//Remove the menu-open class from the parent
ul . removeClass ( 'menu-open' ) ;
//Get the parent li
var parent _li = $this . parent ( "li" ) ;
//Open the target menu and add the menu-open class
checkElement . slideDown ( animationSpeed , function ( ) {
//Add the class active to the parent li
checkElement . addClass ( 'menu-open' ) ;
parent . find ( 'li.active' ) . removeClass ( 'active' ) ;
parent _li . addClass ( 'active' ) ;
//Fix the layout in case the sidebar stretches over the height of the window
_this . layout . fix ( ) ;
} ) ;
}
//if this isn't a link, prevent the page from being redirected
if ( checkElement . is ( '.treeview-menu' ) ) {
e . preventDefault ( ) ;
}
} ) ;
} ;
/ * C o n t r o l S i d e b a r
* === === === === ==
* Adds functionality to the right sidebar
*
* @ type Object
* @ usage $ . AdminLTE . controlSidebar . activate ( options )
* /
$ . AdminLTE . controlSidebar = {
//instantiate the object
activate : function ( ) {
//Get the object
var _this = this ;
//Update options
var o = $ . AdminLTE . options . controlSidebarOptions ;
//Get the sidebar
var sidebar = $ ( o . selector ) ;
//The toggle button
var btn = $ ( o . toggleBtnSelector ) ;
//Listen to the click event
btn . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
//If the sidebar is not open
if ( ! sidebar . hasClass ( 'control-sidebar-open' )
&& ! $ ( 'body' ) . hasClass ( 'control-sidebar-open' ) ) {
//Open the sidebar
_this . open ( sidebar , o . slide ) ;
} else {
_this . close ( sidebar , o . slide ) ;
}
} ) ;
//If the body has a boxed layout, fix the sidebar bg position
var bg = $ ( ".control-sidebar-bg" ) ;
_this . _fix ( bg ) ;
//If the body has a fixed layout, make the control sidebar fixed
if ( $ ( 'body' ) . hasClass ( 'fixed' ) ) {
_this . _fixForFixed ( sidebar ) ;
} else {
//If the content height is less than the sidebar's height, force max height
if ( $ ( '.content-wrapper, .right-side' ) . height ( ) < sidebar . height ( ) ) {
_this . _fixForContent ( sidebar ) ;
}
}
} ,
//Open the control sidebar
open : function ( sidebar , slide ) {
//Slide over content
if ( slide ) {
sidebar . addClass ( 'control-sidebar-open' ) ;
} else {
//Push the content by adding the open class to the body instead
//of the sidebar itself
$ ( 'body' ) . addClass ( 'control-sidebar-open' ) ;
}
} ,
//Close the control sidebar
close : function ( sidebar , slide ) {
if ( slide ) {
sidebar . removeClass ( 'control-sidebar-open' ) ;
} else {
$ ( 'body' ) . removeClass ( 'control-sidebar-open' ) ;
}
} ,
_fix : function ( sidebar ) {
var _this = this ;
if ( $ ( "body" ) . hasClass ( 'layout-boxed' ) ) {
sidebar . css ( 'position' , 'absolute' ) ;
sidebar . height ( $ ( ".wrapper" ) . height ( ) ) ;
$ ( window ) . resize ( function ( ) {
_this . _fix ( sidebar ) ;
} ) ;
} else {
sidebar . css ( {
'position' : 'fixed' ,
'height' : 'auto'
} ) ;
}
} ,
_fixForFixed : function ( sidebar ) {
sidebar . css ( {
'position' : 'fixed' ,
'max-height' : '100%' ,
'overflow' : 'auto' ,
'padding-bottom' : '50px'
} ) ;
} ,
_fixForContent : function ( sidebar ) {
$ ( ".content-wrapper, .right-side" ) . css ( 'min-height' , sidebar . height ( ) ) ;
}
} ;
/ * B o x W i d g e t
* === === ===
* BoxWidget is a plugin to handle collapsing and
* removing boxes from the screen .
*
* @ type Object
* @ usage $ . AdminLTE . boxWidget . activate ( )
* Set all your options in the main $ . AdminLTE . options object
* /
$ . AdminLTE . boxWidget = {
selectors : $ . AdminLTE . options . boxWidgetOptions . boxWidgetSelectors ,
icons : $ . AdminLTE . options . boxWidgetOptions . boxWidgetIcons ,
animationSpeed : $ . AdminLTE . options . animationSpeed ,
activate : function ( _box ) {
var _this = this ;
if ( ! _box ) {
_box = document ; // activate all boxes per default
}
//Listen for collapse event triggers
$ ( _box ) . on ( 'click' , _this . selectors . collapse , function ( e ) {
e . preventDefault ( ) ;
_this . collapse ( $ ( this ) ) ;
} ) ;
//Listen for remove event triggers
$ ( _box ) . on ( 'click' , _this . selectors . remove , function ( e ) {
e . preventDefault ( ) ;
_this . remove ( $ ( this ) ) ;
} ) ;
} ,
collapse : function ( element ) {
var _this = this ;
//Find the box parent
var box = element . parents ( ".box" ) . first ( ) ;
//Find the body and the footer
var box _content = box . find ( "> .box-body, > .box-footer, > form >.box-body, > form > .box-footer" ) ;
if ( ! box . hasClass ( "collapsed-box" ) ) {
//Convert minus into plus
element . children ( ":first" )
. removeClass ( _this . icons . collapse )
. addClass ( _this . icons . open ) ;
//Hide the content
box _content . slideUp ( _this . animationSpeed , function ( ) {
box . addClass ( "collapsed-box" ) ;
} ) ;
} else {
//Convert plus into minus
element . children ( ":first" )
. removeClass ( _this . icons . open )
. addClass ( _this . icons . collapse ) ;
//Show the content
box _content . slideDown ( _this . animationSpeed , function ( ) {
box . removeClass ( "collapsed-box" ) ;
} ) ;
}
} ,
remove : function ( element ) {
//Find the box parent
var box = element . parents ( ".box" ) . first ( ) ;
box . slideUp ( this . animationSpeed ) ;
}
} ;
}
/ * - - - - - - - - - - - - - - - - - -
* - Custom Plugins -
* -- -- -- -- -- -- -- -- --
* All custom plugins are defined below .
* /
/ *
* BOX REFRESH BUTTON
* -- -- -- -- -- -- -- -- --
* This is a custom plugin to use with the component BOX . It allows you to add
* a refresh button to the box . It converts the box ' s state to a loading state .
*
* @ type plugin
* @ usage $ ( "#box-widget" ) . boxRefresh ( options ) ;
* /
( function ( $ ) {
"use strict" ;
$ . fn . boxRefresh = function ( options ) {
// Render options
var settings = $ . extend ( {
//Refresh button selector
trigger : ".refresh-btn" ,
//File source to be loaded (e.g: ajax/src.php)
source : "" ,
//Callbacks
onLoadStart : function ( box ) {
return box ;
} , //Right after the button has been clicked
onLoadDone : function ( box ) {
return box ;
} //When the source has been loaded
} , options ) ;
//The overlay
var overlay = $ ( '<div class="overlay"><div class="fa fa-refresh fa-spin"></div></div>' ) ;
return this . each ( function ( ) {
//if a source is specified
if ( settings . source === "" ) {
if ( window . console ) {
window . console . log ( "Please specify a source first - boxRefresh()" ) ;
}
return ;
}
//the box
var box = $ ( this ) ;
//the button
var rBtn = box . find ( settings . trigger ) . first ( ) ;
//On trigger click
rBtn . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
//Add loading overlay
start ( box ) ;
//Perform ajax call
box . find ( ".box-body" ) . load ( settings . source , function ( ) {
done ( box ) ;
} ) ;
} ) ;
} ) ;
function start ( box ) {
//Add overlay and loading img
box . append ( overlay ) ;
settings . onLoadStart . call ( box ) ;
}
function done ( box ) {
//Remove overlay and loading img
box . find ( overlay ) . remove ( ) ;
settings . onLoadDone . call ( box ) ;
}
} ;
} ) ( jQuery ) ;
/ *
* EXPLICIT BOX ACTIVATION
* -- -- -- -- -- -- -- -- -- -- -- -
* This is a custom plugin to use with the component BOX . It allows you to activate
* a box inserted in the DOM after the app . js was loaded .
*
* @ type plugin
* @ usage $ ( "#box-widget" ) . activateBox ( ) ;
* /
( function ( $ ) {
'use strict' ;
$ . fn . activateBox = function ( ) {
$ . AdminLTE . boxWidget . activate ( this ) ;
} ;
} ) ( jQuery ) ;
/ * *
* Module containing core application logic .
* @ param { jQuery } $ Insulated jQuery object
* @ param { JSON } settings Insulated ` window.snipeit.settings ` object .
* @ return { IIFE } Immediately invoked . Returns self .
* /
var lineOptions = {
legend : {
position : "bottom"
} ,
scales : {
yAxes : [ {
ticks : {
fontColor : "rgba(0,0,0,0.5)" ,
fontStyle : "bold" ,
beginAtZero : true ,
maxTicksLimit : 5 ,
padding : 20
} ,
gridLines : {
drawTicks : false ,
display : false
}
} ] ,
xAxes : [ {
gridLines : {
zeroLineColor : "transparent"
} ,
ticks : {
padding : 20 ,
fontColor : "rgba(0,0,0,0.5)" ,
fontStyle : "bold"
}
} ]
}
} ;
var pieOptions = {
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke : true ,
//String - The colour of each segment stroke
segmentStrokeColor : "#fff" ,
//Number - The width of each segment stroke
segmentStrokeWidth : 1 ,
//Number - The percentage of the chart that we cut out of the middle
percentageInnerCutout : 50 , // This is 0 for Pie charts
//Number - Amount of animation steps
animationSteps : 100 ,
//String - Animation easing effect
animationEasing : "easeOutBounce" ,
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true ,
//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false ,
//Boolean - whether to make the chart responsive to window resizing
responsive : true ,
// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
maintainAspectRatio : false ,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li>" +
"<i class='fa fa-circle-o' style='color: <%=segments[i].fillColor%>'></i>" +
"<%if(segments[i].label){%><%=segments[i].label%><%}%> foo</li><%}%></ul>" ,
//String - A tooltip template
tooltipTemplate : "<%=value %> <%=label%> "
} ;
//-----------------
//- END PIE CHART -
//-----------------
( function ( $ , settings ) {
var Components = { } ;
Components . modals = { } ;
// confirm delete modal
Components . modals . confirmDelete = function ( ) {
var $el = $ ( 'table' ) ;
var events = {
'click' : function ( evnt ) {
var $context = $ ( this ) ;
var $dataConfirmModal = $ ( '#dataConfirmModal' ) ;
var href = $context . attr ( 'href' ) ;
var message = $context . attr ( 'data-content' ) ;
var title = $context . attr ( 'data-title' ) ;
$ ( '#myModalLabel' ) . text ( title ) ;
$dataConfirmModal . find ( '.modal-body' ) . text ( message ) ;
$ ( '#deleteForm' ) . attr ( 'action' , href ) ;
$dataConfirmModal . modal ( {
show : true
} ) ;
return false ;
}
} ;
var render = function ( ) {
$el . on ( 'click' , '.delete-asset' , events [ 'click' ] ) ;
} ;
return {
render : render
} ;
} ;
/ * *
* Application start point
* Component definition stays out of load event , execution only happens .
* /
$ ( function ( ) {
new Components . modals . confirmDelete ( ) . render ( ) ;
} ) ;
} ( jQuery , window . snipeit . settings ) ) ;
$ ( document ) . ready ( function ( ) {
/ *
* Slideout help menu
* /
$ ( '.slideout-menu-toggle' ) . on ( 'click' , function ( event ) {
console . log ( 'clicked' ) ;
event . preventDefault ( ) ;
// create menu variables
var slideoutMenu = $ ( '.slideout-menu' ) ;
var slideoutMenuWidth = $ ( '.slideout-menu' ) . width ( ) ;
// toggle open class
slideoutMenu . toggleClass ( "open" ) ;
// slide menu
if ( slideoutMenu . hasClass ( "open" ) ) {
slideoutMenu . show ( ) ;
slideoutMenu . animate ( {
right : "0px"
} ) ;
} else {
slideoutMenu . animate ( {
right : - slideoutMenuWidth
} , "-350px" ) ;
slideoutMenu . fadeOut ( ) ;
}
} ) ;
/ *
* iCheck checkbox plugin
* /
$ ( 'input[type="checkbox"].minimal, input[type="radio"].minimal' ) . iCheck ( {
checkboxClass : 'icheckbox_minimal-blue' ,
radioClass : 'iradio_minimal-blue'
} ) ;
/ *
* Select2
* /
var iOS = /iPhone|iPad|iPod/ . test ( navigator . userAgent ) && ! window . MSStream ;
if ( ! iOS )
{
// Vue collision: Avoid overriding a vue select2 instance
// by checking to see if the item has already been select2'd.
$ ( 'select.select2:not(".select2-hidden-accessible")' ) . each ( function ( i , obj ) {
{
$ ( obj ) . select2 ( ) ;
}
} ) ;
}
$ ( '.datepicker' ) . datepicker ( ) ;
var datepicker = $ . fn . datepicker . noConflict ( ) ; // return $.fn.datepicker to previously assigned value
$ . fn . bootstrapDP = datepicker ;
$ ( '.datepicker' ) . datepicker ( ) ;
// Crazy select2 rich dropdowns with images!
$ ( '.js-data-ajax' ) . each ( function ( i , item ) {
var link = $ ( item ) ;
var endpoint = link . data ( "endpoint" ) ;
var select = link . data ( "select" ) ;
link . select2 ( {
ajax : {
// the baseUrl includes a trailing slash
url : baseUrl + 'api/v1/' + endpoint + '/selectlist' ,
dataType : 'json' ,
delay : 250 ,
headers : {
"X-Requested-With" : 'XMLHttpRequest' ,
"X-CSRF-TOKEN" : $ ( 'meta[name="csrf-token"]' ) . attr ( 'content' )
} ,
data : function ( params ) {
var data = {
search : params . term ,
page : params . page || 1
} ;
return data ;
} ,
processResults : function ( data , params ) {
params . page = params . page || 1 ;
var answer = {
results : data . items ,
pagination : {
more : "true" //(params.page < data.page_count)
}
} ;
return answer ;
} ,
cache : true
} ,
escapeMarkup : function ( markup ) { return markup ; } , // let our custom formatter work
templateResult : formatDatalist ,
templateSelection : formatDataSelection
} ) ;
} ) ;
function formatDatalist ( datalist ) {
var loading _markup = '<i class="fa fa-spinner fa-spin" aria-hidden="true"></i> Loading...' ;
if ( datalist . loading ) {
return loading _markup ;
}
var markup = "<div class='clearfix'>" ;
markup += "<div class='pull-left' style='padding-right: 10px;'>" ;
if ( datalist . image ) {
markup += "<div style='width: 30px;'><img src='" + datalist . image + "' style='max-height: 20px; max-width: 30px;'></div>" ;
} else {
markup += "<div style='height: 20px; width: 30px;'></div>" ;
}
markup += "</div><div>" + datalist . text + "</div>" ;
markup += "</div>" ;
return markup ;
}
function formatDataSelection ( datalist ) {
return datalist . text ;
}
// This handles the radio button selectors for the checkout-to-foo options
// on asset checkout and also on asset edit
$ ( function ( ) {
$ ( 'input[name=checkout_to_type]' ) . on ( "change" , function ( ) {
var assignto _type = $ ( 'input[name=checkout_to_type]:checked' ) . val ( ) ;
var userid = $ ( '#assigned_user option:selected' ) . val ( ) ;
if ( assignto _type == 'asset' ) {
$ ( '#current_assets_box' ) . fadeOut ( ) ;
$ ( '#assigned_asset' ) . show ( ) ;
$ ( '#assigned_user' ) . hide ( ) ;
$ ( '#assigned_location' ) . hide ( ) ;
$ ( '.notification-callout' ) . fadeOut ( ) ;
} else if ( assignto _type == 'location' ) {
$ ( '#current_assets_box' ) . fadeOut ( ) ;
$ ( '#assigned_asset' ) . hide ( ) ;
$ ( '#assigned_user' ) . hide ( ) ;
$ ( '#assigned_location' ) . show ( ) ;
$ ( '.notification-callout' ) . fadeOut ( ) ;
} else {
$ ( '#assigned_asset' ) . hide ( ) ;
$ ( '#assigned_user' ) . show ( ) ;
$ ( '#assigned_location' ) . hide ( ) ;
if ( userid ) {
$ ( '#current_assets_box' ) . fadeIn ( ) ;
}
$ ( '.notification-callout' ) . fadeIn ( ) ;
}
} ) ;
} ) ;
} ) ;
/ *
*
* Snipe - IT Universal Modal support
*
* Enables modal dialogs to create sub - resources throughout Snipe - IT
*
* /
/ *
HOW TO USE
Create a Button looking like this :
< a href = '{{ route(' modal . user ') }}' data - toggle = "modal" data - target = "#createModal" data - dependency = "user" data - select = 'assigned_to' class = "btn btn-sm btn-default" > New < / a >
If you don 't have access to Blade commands (like {{ and }}, etc), you can hard-code a URL as the ' href '
data - toggle = "modal" - required for Bootstrap Modals
data - target = "#createModal" - fixed ID for the modal , do not change
data - dependency = "user" - which Snipe - IT model you ' re going to be creating .
data - select = "assigned_to" - What is the * ID * of the select - dropdown that you 're going to be adding to, if the modal-create was a success? Be on the lookout for duplicate ID' s , it will confuse this library !
class = "btn btn-sm btn-default" - makes it look button - ey , feel free to change : )
* /
$ ( function ( ) {
//handle modal-add-interstitial calls
var model , select ;
if ( $ ( '#createModal' ) . length == 0 ) {
$ ( 'body' ) . append ( '<div class="modal fade" id="createModal"></div><!-- /.modal -->' ) ;
}
$ ( '#createModal' ) . on ( "show.bs.modal" , function ( event ) {
var link = $ ( event . relatedTarget ) ;
model = link . data ( "dependency" ) ;
select = link . data ( "select" ) ;
$ ( '#createModal' ) . load ( link . attr ( 'href' ) , function ( ) {
//do we need to re-select2 this, after load? Probably.
$ ( '#createModal' ) . find ( 'select.select2' ) . select2 ( ) ;
} ) ;
} ) ;
$ ( '#createModal' ) . on ( 'click' , '#modal-save' , function ( ) {
var data = { } ;
//console.warn("We are about to SAVE!!! for model: "+model+" and select ID: "+select);
$ ( '.modal-body input:visible' ) . each ( function ( index , elem ) {
var bits = elem . id . split ( "-" ) ;
if ( bits [ 0 ] === "modal" ) {
data [ bits [ 1 ] ] = $ ( elem ) . val ( ) ;
}
} ) ;
//this can probably get replaced with a normal 'serialize' instead
$ ( '.modal-body select:visible' ) . each ( function ( index , elem ) {
var bits = elem . id . split ( "-" ) ;
data [ bits [ 1 ] ] = $ ( elem ) . val ( ) ;
} ) ;
data . _token = Laravel . csrfToken ;
$ . ajax ( {
type : 'POST' ,
url : baseUrl + "/api/v1/" + model + "s" ,
headers : {
"X-Requested-With" : 'XMLHttpRequest' ,
"X-CSRF-TOKEN" : $ ( 'meta[name="csrf-token"]' ) . attr ( 'content' )
} ,
data : data ,
success : function ( result ) {
console . dir ( result ) ;
if ( result . status == "error" ) {
var error _message = "" ;
for ( var field in result . messages ) {
error _message += "<li>Problem(s) with field <i><strong>" + field + "</strong></i>: " + result . messages [ field ] ;
console . dir ( result . messages ) ;
console . log ( 'error_messages are: ' + error _message ) ;
}
$ ( '#modal_error_msg' ) . html ( error _message ) . show ( ) ;
return false ;
}
var id = result . payload . id ;
var name = result . payload . name || ( result . payload . first _name + " " + result . payload . last _name ) ;
if ( ! id || ! name ) {
console . error ( "Could not find resulting name or ID from modal-create. Name: " + name + ", id: " + id ) ;
return false ;
}
$ ( '#createModal' ) . modal ( 'hide' ) ;
$ ( '#createModal' ) . html ( "" ) ;
// "select" is the original drop-down menu that someone
// clicked 'add' on to add a new 'thing'
// this code adds the newly created object to that select
var selector = document . getElementById ( select ) ;
console . warn ( "The selector we should've selecte dis: " + select ) ;
console . dir ( selector ) ;
if ( ! selector ) {
return false ;
}
console . warn ( "onChange Selector Thing should've activated? Here's the selector" ) ;
console . dir ( selector ) ;
selector . options [ selector . length ] = new Option ( name , id ) ;
selector . selectedIndex = selector . length - 1 ;
$ ( selector ) . trigger ( "change" ) ;
if ( window . fetchCustomFields ) {
fetchCustomFields ( ) ;
}
} ,
error : function ( result ) {
msg = result . responseJSON . messages || result . responseJSON . error ;
$ ( '#modal_error_msg' ) . html ( "Server Error: " + msg ) . show ( ) ;
}
} ) ;
} ) ;
} ) ;