Archive: Namaste PHP AMQP framework v1.0 (2017-2020)
952 days continuous production uptime, 40k+ tp/s single node. Original corpo Bitbucket history not included — clean archive commit.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
Warning!
|
||||
|
||||
All Javascript modules are already included in mdb.js file.
|
||||
You should never include both, mdb.js and modules into your project.
|
||||
Modules are intended for developers who want to minimize a size of a website,
|
||||
by including only chosen component instead of entire library.
|
||||
|
||||
In that case you should skip mdb.js file and import all modules files which you are intending to use.
|
||||
|
||||
I.e.
|
||||
If you want to use only charts or lightbox you should include chart.js and lightbox.js and make sure
|
||||
that you are not including mdb.js into your project.
|
||||
If you don't know which components do you want to use now or in a future, you should include mdb.js
|
||||
and skip all other module files.
|
||||
File diff suppressed because it is too large
Load Diff
Vendored
+3
File diff suppressed because one or more lines are too long
+3927
File diff suppressed because it is too large
Load Diff
+7
File diff suppressed because one or more lines are too long
Vendored
+9842
File diff suppressed because it is too large
Load Diff
Vendored
+4
File diff suppressed because one or more lines are too long
Vendored
+10220
File diff suppressed because it is too large
Load Diff
Vendored
+4
File diff suppressed because one or more lines are too long
+4
File diff suppressed because one or more lines are too long
Vendored
+2
File diff suppressed because one or more lines are too long
+28411
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,10 @@
|
||||
// Animations
|
||||
|
||||
$(function() {
|
||||
$('.arrow-r').on('click', function() {
|
||||
//Reset all but the current
|
||||
$('.arrow-r').not(this).find('.fa-angle-down').removeClass('rotate-element');
|
||||
//Rotate/reset the clicked one
|
||||
$(this).find('.fa-angle-down').toggleClass('rotate-element');
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Material Design for Bootstrap
|
||||
* MDB Autocomplete Plugin
|
||||
*/
|
||||
|
||||
$.fn.mdb_autocomplete = function (options) {
|
||||
|
||||
// Default options
|
||||
var defaults = {
|
||||
data: {}
|
||||
};
|
||||
|
||||
// Get options
|
||||
options = $.extend(defaults, options);
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
// text input
|
||||
var $input = $(this);
|
||||
|
||||
// assign data from options
|
||||
var data = options.data;
|
||||
|
||||
if (Object.keys(data).length) {
|
||||
|
||||
var $autocomplete = $('<ul class="mdb-autocomplete-wrap"></ul>');
|
||||
|
||||
$autocomplete.insertAfter($(this));
|
||||
};
|
||||
|
||||
// Listen if key was pressed
|
||||
$input.on('keyup', function (e) {
|
||||
|
||||
// get value from input
|
||||
var q = $input.val();
|
||||
|
||||
$autocomplete.empty();
|
||||
|
||||
// check if input isn't empty
|
||||
if (q.length) {
|
||||
|
||||
for (var item in data) {
|
||||
|
||||
// check if item contains value that we're looking for
|
||||
if (data[item].toLowerCase().indexOf(q.toLowerCase()) !== -1) {
|
||||
var option = $('<li>' + data[item] + '</li>');
|
||||
|
||||
$autocomplete.append(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (e.which == 13) {
|
||||
$autocomplete.children(":first").trigger('click');
|
||||
$autocomplete.empty();
|
||||
}
|
||||
|
||||
if (q.length == 0) {
|
||||
$('.mdb-autocomplete-clear').css('visibility', 'hidden');
|
||||
} else {
|
||||
$('.mdb-autocomplete-clear').css('visibility', 'visible');
|
||||
}
|
||||
});
|
||||
|
||||
$autocomplete.on('click', 'li', function () {
|
||||
|
||||
// Set input value after click
|
||||
$input.val($(this).text());
|
||||
|
||||
// Clear autocomplete
|
||||
$autocomplete.empty();
|
||||
});
|
||||
|
||||
$('.mdb-autocomplete-clear').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$input.val('');
|
||||
$(this).css('visibility', 'hidden');
|
||||
$autocomplete.empty();
|
||||
$(this).parent().find('label').removeClass('active');
|
||||
});
|
||||
});
|
||||
};
|
||||
Executable
+157
@@ -0,0 +1,157 @@
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
$(document).ready(function () {
|
||||
|
||||
// jQuery reverse
|
||||
$.fn.reverse = [].reverse;
|
||||
|
||||
// Hover behaviour: make sure this doesn't work on .click-to-toggle FABs!
|
||||
$(document).on('mouseenter.fixedActionBtn', '.fixed-action-btn:not(.click-to-toggle)', function () {
|
||||
var $this = $(this);
|
||||
openFABMenu($this);
|
||||
});
|
||||
$(document).on('mouseleave.fixedActionBtn', '.fixed-action-btn:not(.click-to-toggle)', function () {
|
||||
var $this = $(this);
|
||||
closeFABMenu($this);
|
||||
});
|
||||
|
||||
// Toggle-on-click behaviour.
|
||||
$(document).on('click.fixedActionBtn', '.fixed-action-btn.click-to-toggle > a', function () {
|
||||
var $this = $(this);
|
||||
var $menu = $this.parent();
|
||||
if ($menu.hasClass('active')) {
|
||||
closeFABMenu($menu);
|
||||
} else {
|
||||
openFABMenu($menu);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$.fn.extend({
|
||||
openFAB: function openFAB() {
|
||||
openFABMenu($(this));
|
||||
},
|
||||
closeFAB: function closeFAB() {
|
||||
closeFABMenu($(this));
|
||||
}
|
||||
});
|
||||
|
||||
var openFABMenu = function openFABMenu(btn) {
|
||||
var $this = btn;
|
||||
if ($this.hasClass('active') === false) {
|
||||
|
||||
// Get direction option
|
||||
var horizontal = $this.hasClass('horizontal');
|
||||
var offsetY = void 0,
|
||||
offsetX = void 0;
|
||||
|
||||
if (horizontal === true) {
|
||||
offsetX = 40;
|
||||
} else {
|
||||
offsetY = 40;
|
||||
}
|
||||
|
||||
$this.addClass('active');
|
||||
$this.find('ul .btn-floating').velocity({
|
||||
scaleY: '.4',
|
||||
scaleX: '.4',
|
||||
translateY: offsetY + 'px',
|
||||
translateX: offsetX + 'px'
|
||||
}, {
|
||||
duration: 0
|
||||
});
|
||||
|
||||
var time = 0;
|
||||
$this.find('ul .btn-floating').reverse().each(function () {
|
||||
$(this).velocity({
|
||||
opacity: '1',
|
||||
scaleX: '1',
|
||||
scaleY: '1',
|
||||
translateY: '0',
|
||||
translateX: '0'
|
||||
}, {
|
||||
duration: 80,
|
||||
delay: time
|
||||
});
|
||||
time += 40;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var closeFABMenu = function closeFABMenu(btn) {
|
||||
$this = btn;
|
||||
// Get direction option
|
||||
var horizontal = $this.hasClass('horizontal');
|
||||
var offsetY = void 0,
|
||||
offsetX = void 0;
|
||||
|
||||
if (horizontal === true) {
|
||||
offsetX = 40;
|
||||
} else {
|
||||
offsetY = 40;
|
||||
}
|
||||
|
||||
$this.removeClass('active');
|
||||
var time = 0;
|
||||
$this.find('ul .btn-floating').velocity('stop', true);
|
||||
$this.find('ul .btn-floating').velocity({
|
||||
opacity: '0',
|
||||
scaleX: '.4',
|
||||
scaleY: '.4',
|
||||
translateY: offsetY + 'px',
|
||||
translateX: offsetX + 'px'
|
||||
}, {
|
||||
duration: 80
|
||||
});
|
||||
};
|
||||
|
||||
$('.fixed-action-btn').on({
|
||||
click: function click(e) {
|
||||
e.preventDefault();
|
||||
toggleFABMenu($('.fixed-action-btn'));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
function toggleFABMenu(btn) {
|
||||
|
||||
$this = btn;
|
||||
if ($this.hasClass('active') === false) {
|
||||
$this.addClass('active');
|
||||
$this.find('ul .btn-floating').velocity({
|
||||
scaleY: '.4',
|
||||
scaleX: '.4',
|
||||
translateY: '40px'
|
||||
}, {
|
||||
duration: 0
|
||||
});
|
||||
|
||||
var time = 0;
|
||||
$this.find('ul .btn-floating').reverse().each(function () {
|
||||
$(this).velocity({
|
||||
opacity: '1',
|
||||
scaleX: '1',
|
||||
scaleY: '1',
|
||||
translateY: '0'
|
||||
}, {
|
||||
duration: 80,
|
||||
delay: time
|
||||
});
|
||||
time += 40;
|
||||
});
|
||||
} else {
|
||||
$this.removeClass('active');
|
||||
var _time = 0;
|
||||
$this.find('ul .btn-floating').velocity('stop', true);
|
||||
$this.find('ul .btn-floating').velocity({
|
||||
opacity: '0',
|
||||
scaleX: '.4',
|
||||
scaleY: '.4',
|
||||
translateY: '40px'
|
||||
}, {
|
||||
duration: 80
|
||||
});
|
||||
}
|
||||
}
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,50 @@
|
||||
/* CARD REVEAL */
|
||||
|
||||
(function ($) {
|
||||
$(document).ready(function () {
|
||||
|
||||
$(document).on('click.card', '.card', function (e) {
|
||||
if ($(this).find('.card-reveal').length) {
|
||||
if ($(e.target).is($('.card-reveal .card-title')) || $(e.target).is($('.card-reveal .card-title i'))) {
|
||||
// Make Reveal animate down and display none
|
||||
$(this).find('.card-reveal').velocity({
|
||||
translateY: 0
|
||||
}, {
|
||||
duration: 225,
|
||||
queue: false,
|
||||
easing: 'easeInOutQuad',
|
||||
complete: function () {
|
||||
$(this).css({
|
||||
display: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if ($(e.target).is($('.card .activator')) ||
|
||||
$(e.target).is($('.card .activator i'))) {
|
||||
$(this).find('.card-reveal').css({
|
||||
display: 'block'
|
||||
}).velocity("stop", false).velocity({
|
||||
translateY: '-100%'
|
||||
}, {
|
||||
duration: 300,
|
||||
queue: false,
|
||||
easing: 'easeInOutQuad'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}(jQuery));
|
||||
|
||||
//Social reveal
|
||||
$(document).ready(function ($) {
|
||||
|
||||
$('.card-share > a').on('click', function (e) {
|
||||
e.preventDefault() // prevent default action - hash doesn't appear in url
|
||||
$(this).parent().find('div').toggleClass('social-reveal-active');
|
||||
$(this).toggleClass('share-expanded');
|
||||
});
|
||||
});
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
'use strict';
|
||||
|
||||
/* CARD REVEAL */
|
||||
(function ($) {
|
||||
$(document).ready(function () {
|
||||
|
||||
$(document).on('click.card', '.card', function (e) {
|
||||
|
||||
var $this = $(this);
|
||||
var isReveal = $this.find('.card-reveal').length;
|
||||
|
||||
if (isReveal) {
|
||||
|
||||
var $clicked = $(e.target);
|
||||
var isTitle = $clicked.is('.card-reveal .card-title');
|
||||
var isTitleIcon = $clicked.is('.card-reveal .card-title i');
|
||||
var isActivator = $clicked.is('.card .activator');
|
||||
var isActivatorIcon = $clicked.is('.card .activator i');
|
||||
|
||||
if (isTitle || isTitleIcon) {
|
||||
// down
|
||||
|
||||
$this.find('.card-reveal').velocity({
|
||||
translateY: 0
|
||||
}, {
|
||||
duration: 225,
|
||||
queue: false,
|
||||
easing: 'easeInOutQuad',
|
||||
complete: function complete() {
|
||||
$(this).css({
|
||||
display: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (isActivator || isActivatorIcon) {
|
||||
// up
|
||||
|
||||
$this.find('.card-reveal').css({
|
||||
display: 'block'
|
||||
}).velocity('stop', false).velocity({
|
||||
translateY: '-100%'
|
||||
}, {
|
||||
duration: 300,
|
||||
queue: false,
|
||||
easing: 'easeInOutQuad'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('.rotate-btn').on('click', function () {
|
||||
|
||||
var cardId = $(this).attr('data-card');
|
||||
$('#' + cardId).toggleClass('flipped');
|
||||
});
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
// Social reveal
|
||||
$(document).ready(function ($) {
|
||||
|
||||
$('.card-share > a').on('click', function (e) {
|
||||
e.preventDefault(); // prevent default action - hash doesn't appear in url
|
||||
$(this).parent().find('div').toggleClass('social-reveal-active');
|
||||
$(this).toggleClass('share-expanded');
|
||||
});
|
||||
});
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
/* CHARACTER COUNTER */
|
||||
|
||||
(function ($) {
|
||||
|
||||
$.fn.characterCounter = function () {
|
||||
return this.each(function () {
|
||||
|
||||
var itHasLengthAttribute = $(this).attr('length') !== undefined;
|
||||
|
||||
if (itHasLengthAttribute) {
|
||||
$(this).on('input', updateCounter);
|
||||
$(this).on('focus', updateCounter);
|
||||
$(this).on('blur', removeCounterElement);
|
||||
|
||||
addCounterElement($(this));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function updateCounter() {
|
||||
var maxLength = Number($(this).attr('length'));
|
||||
var actualLength = Number($(this).val().length);
|
||||
var isValidLength = actualLength <= maxLength;
|
||||
|
||||
$(this).parent().find('span[class="character-counter"]').html(actualLength + '/' + maxLength);
|
||||
|
||||
addInputStyle(isValidLength, $(this));
|
||||
}
|
||||
|
||||
function addCounterElement($input) {
|
||||
var $counterElement = $('<span/>').addClass('character-counter').css('float', 'right').css('font-size', '12px').css('height', 1);
|
||||
|
||||
$input.parent().append($counterElement);
|
||||
}
|
||||
|
||||
function removeCounterElement() {
|
||||
$(this).parent().find('span[class="character-counter"]').html('');
|
||||
}
|
||||
|
||||
function addInputStyle(isValidLength, $input) {
|
||||
var inputHasInvalidClass = $input.hasClass('invalid');
|
||||
if (isValidLength && inputHasInvalidClass) {
|
||||
$input.removeClass('invalid');
|
||||
} else if (!isValidLength && !inputHasInvalidClass) {
|
||||
$input.removeClass('valid');
|
||||
$input.addClass('invalid');
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('input, textarea').characterCounter();
|
||||
});
|
||||
})(jQuery);
|
||||
Executable
+12757
File diff suppressed because it is too large
Load Diff
Executable
+284
@@ -0,0 +1,284 @@
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
|
||||
var chipsHandleEvents = false;
|
||||
var materialChipsDefaults = {
|
||||
data: [],
|
||||
placeholder: '',
|
||||
secondaryPlaceholder: ''
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
// Handle removal of static chips.
|
||||
$(document).on('click', '.chip .close', function () {
|
||||
|
||||
var $this = $(this);
|
||||
var $chips = $this.closest('.chips');
|
||||
|
||||
if ($chips.data('initialized')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this.closest('.chip').remove();
|
||||
});
|
||||
});
|
||||
|
||||
$.fn.material_chip = function (options) {
|
||||
var self = this;
|
||||
this.$el = $(this);
|
||||
this.$document = $(document);
|
||||
this.SELS = {
|
||||
CHIPS: '.chips',
|
||||
CHIP: '.chip',
|
||||
INPUT: 'input',
|
||||
DELETE: '.fa',
|
||||
SELECTED_CHIP: '.selected'
|
||||
};
|
||||
|
||||
if (options === 'data') {
|
||||
return this.$el.data('chips');
|
||||
}
|
||||
|
||||
if (options === 'options') {
|
||||
return this.$el.data('options');
|
||||
}
|
||||
|
||||
this.$el.data('options', $.extend({}, materialChipsDefaults, options));
|
||||
|
||||
// Initialize
|
||||
this.init = function () {
|
||||
var i = 0;
|
||||
self.$el.each(function () {
|
||||
|
||||
var $chips = $(this);
|
||||
if ($chips.data('initialized')) {
|
||||
return;
|
||||
} // Prevent double initialization.
|
||||
|
||||
var options = $chips.data('options');
|
||||
if (!options.data || !(options.data instanceof Array)) {
|
||||
options.data = [];
|
||||
}
|
||||
|
||||
$chips.data('chips', options.data);
|
||||
$chips.data('index', i);
|
||||
$chips.data('initialized', true);
|
||||
|
||||
if (!$chips.hasClass(self.SELS.CHIPS)) {
|
||||
$chips.addClass('chips');
|
||||
}
|
||||
|
||||
self.chips($chips);
|
||||
i++;
|
||||
});
|
||||
};
|
||||
|
||||
this.handleEvents = function () {
|
||||
var SELS = self.SELS;
|
||||
|
||||
self.$document.on('click', SELS.CHIPS, function (e) {
|
||||
$(e.target).find(SELS.INPUT).focus();
|
||||
});
|
||||
|
||||
self.$document.on('click', SELS.CHIP, function () {
|
||||
$(SELS.CHIP).removeClass('selected');
|
||||
$(this).toggleClass('selected');
|
||||
});
|
||||
|
||||
self.$document.on('keydown', function (e) {
|
||||
if ($(e.target).is('input, textarea')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// delete
|
||||
var $chip = self.$document.find(SELS.CHIP + SELS.SELECTED_CHIP);
|
||||
var $chips = $chip.closest(SELS.CHIPS);
|
||||
var length = $chip.siblings(SELS.CHIP).length;
|
||||
var index = void 0;
|
||||
|
||||
if (!$chip.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var isBackspaceOrDelete = e.which === 8 || e.which === 46;
|
||||
var isLeftArrow = e.which === 37;
|
||||
var isRightArrow = e.which === 39;
|
||||
|
||||
if (isBackspaceOrDelete) {
|
||||
e.preventDefault();
|
||||
var chipsIndex = $chips.data('index');
|
||||
index = $chip.index();
|
||||
self.deleteChip(chipsIndex, index, $chips);
|
||||
var selectIndex = null;
|
||||
|
||||
if (index + 1 < length) {
|
||||
selectIndex = index;
|
||||
} else if (index === length || index + 1 === length) {
|
||||
selectIndex = length - 1;
|
||||
}
|
||||
|
||||
if (selectIndex < 0) {
|
||||
selectIndex = null;
|
||||
}
|
||||
|
||||
if (selectIndex !== null) {
|
||||
self.selectChip(chipsIndex, selectIndex, $chips);
|
||||
}
|
||||
if (!length) {
|
||||
$chips.find('input').focus();
|
||||
}
|
||||
} else if (isLeftArrow) {
|
||||
|
||||
index = $chip.index() - 1;
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
$(SELS.CHIP).removeClass('selected');
|
||||
self.selectChip($chips.data('index'), index, $chips);
|
||||
} else if (isRightArrow) {
|
||||
|
||||
index = $chip.index() + 1;
|
||||
$(SELS.CHIP).removeClass('selected');
|
||||
if (index > length) {
|
||||
$chips.find('input').focus();
|
||||
return;
|
||||
}
|
||||
self.selectChip($chips.data('index'), index, $chips);
|
||||
}
|
||||
});
|
||||
|
||||
self.$document.on('focusin', SELS.CHIPS + ' ' + SELS.INPUT, function (e) {
|
||||
$(e.target).closest(SELS.CHIPS).addClass('focus');
|
||||
$(SELS.CHIP).removeClass('selected');
|
||||
});
|
||||
|
||||
self.$document.on('focusout', SELS.CHIPS + ' ' + SELS.INPUT, function (e) {
|
||||
$(e.target).closest(SELS.CHIPS).removeClass('focus');
|
||||
});
|
||||
|
||||
self.$document.on('keydown', SELS.CHIPS + ' ' + SELS.INPUT, function (e) {
|
||||
var $target = $(e.target);
|
||||
var $chips = $target.closest(SELS.CHIPS);
|
||||
var chipsIndex = $chips.data('index');
|
||||
var chipsLength = $chips.children(SELS.CHIP).length;
|
||||
|
||||
var isEnter = e.which === 13;
|
||||
|
||||
if (isEnter) {
|
||||
e.preventDefault();
|
||||
self.addChip(chipsIndex, {
|
||||
tag: $target.val()
|
||||
}, $chips);
|
||||
$target.val('');
|
||||
return;
|
||||
}
|
||||
|
||||
var isLeftArrowOrDelete = e.keyCode === 8 || e.keyCode === 37;
|
||||
var isValueEmpty = $target.val() === '';
|
||||
|
||||
if (isLeftArrowOrDelete && isValueEmpty && chipsLength) {
|
||||
self.selectChip(chipsIndex, chipsLength - 1, $chips);
|
||||
$target.blur();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
self.$document.on('click', SELS.CHIPS + ' ' + SELS.DELETE, function (e) {
|
||||
var $target = $(e.target);
|
||||
var $chips = $target.closest(SELS.CHIPS);
|
||||
var $chip = $target.closest(SELS.CHIP);
|
||||
e.stopPropagation();
|
||||
self.deleteChip($chips.data('index'), $chip.index(), $chips);
|
||||
$chips.find('input').focus();
|
||||
});
|
||||
};
|
||||
|
||||
this.chips = function ($chips) {
|
||||
var html = '';
|
||||
$chips.data('chips').forEach(function (elem) {
|
||||
html += self.renderChip(elem);
|
||||
});
|
||||
html += '<input class="input" placeholder="">';
|
||||
$chips.html(html);
|
||||
self.setPlaceholder($chips);
|
||||
};
|
||||
|
||||
this.renderChip = function (elem) {
|
||||
if (!elem.tag) {
|
||||
return;
|
||||
}
|
||||
|
||||
var html = '<div class="chip">' + elem.tag;
|
||||
|
||||
if (elem.image) {
|
||||
html += ' <img src="' + elem.image + '"> ';
|
||||
}
|
||||
|
||||
html += '<i class="close fa fa-times"></i>';
|
||||
html += '</div>';
|
||||
return html;
|
||||
};
|
||||
|
||||
this.setPlaceholder = function ($chips) {
|
||||
var options = $chips.data('options');
|
||||
if ($chips.data('chips').length && options.placeholder) {
|
||||
$chips.find('input').prop('placeholder', options.placeholder);
|
||||
} else if (!$chips.data('chips').length && options.secondaryPlaceholder) {
|
||||
$chips.find('input').prop('placeholder', options.secondaryPlaceholder);
|
||||
}
|
||||
};
|
||||
|
||||
this.isValid = function ($chips, elem) {
|
||||
var chips = $chips.data('chips');
|
||||
var exists = false;
|
||||
for (var i = 0; i < chips.length; i++) {
|
||||
if (chips[i].tag === elem.tag) {
|
||||
exists = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return elem.tag !== '' && !exists;
|
||||
};
|
||||
|
||||
this.addChip = function (chipsIndex, elem, $chips) {
|
||||
if (!self.isValid($chips, elem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var chipHtml = self.renderChip(elem);
|
||||
$chips.data('chips').push(elem);
|
||||
$(chipHtml).insertBefore($chips.find('input'));
|
||||
$chips.trigger('chip.add', elem);
|
||||
self.setPlaceholder($chips);
|
||||
};
|
||||
|
||||
this.deleteChip = function (chipsIndex, chipIndex, $chips) {
|
||||
var chip = $chips.data('chips')[chipIndex];
|
||||
$chips.find('.chip').eq(chipIndex).remove();
|
||||
$chips.data('chips').splice(chipIndex, 1);
|
||||
$chips.trigger('chip.delete', chip);
|
||||
self.setPlaceholder($chips);
|
||||
};
|
||||
|
||||
this.selectChip = function (chipsIndex, chipIndex, $chips) {
|
||||
var $chip = $chips.find('.chip').eq(chipIndex);
|
||||
if ($chip && $chip.hasClass('selected') === false) {
|
||||
$chip.addClass('selected');
|
||||
$chips.trigger('chip.select', $chips.data('chips')[chipIndex]);
|
||||
}
|
||||
};
|
||||
|
||||
this.getChipsElement = function (index, $chips) {
|
||||
return $chips.eq(index);
|
||||
};
|
||||
|
||||
// init
|
||||
this.init();
|
||||
|
||||
if (!chipsHandleEvents) {
|
||||
this.handleEvents();
|
||||
chipsHandleEvents = true;
|
||||
}
|
||||
};
|
||||
})(jQuery);
|
||||
Executable
+160
@@ -0,0 +1,160 @@
|
||||
'use strict';
|
||||
|
||||
/* COLLAPSIBLE */
|
||||
|
||||
(function ($) {
|
||||
$.fn.collapsible = function (options) {
|
||||
var defaults = {
|
||||
accordion: undefined
|
||||
};
|
||||
|
||||
options = $.extend(defaults, options);
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
var $panel_headers = $(this).find('> li > .collapsible-header');
|
||||
|
||||
var collapsible_type = $this.data('collapsible');
|
||||
|
||||
// Turn off any existing event handlers
|
||||
$this.off('click.collapse', '.collapsible-header');
|
||||
$panel_headers.off('click.collapse');
|
||||
|
||||
/** **************
|
||||
Helper Functions
|
||||
****************/
|
||||
|
||||
// Accordion Open
|
||||
function accordionOpen(object) {
|
||||
$panel_headers = $this.find('> li > .collapsible-header');
|
||||
if (object.hasClass('active')) {
|
||||
object.parent().addClass('active');
|
||||
} else {
|
||||
object.parent().removeClass('active');
|
||||
}
|
||||
if (object.parent().hasClass('active')) {
|
||||
object.siblings('.collapsible-body').stop(true, false).slideDown({
|
||||
duration: 350,
|
||||
easing: 'easeOutQuart',
|
||||
queue: false,
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
object.siblings('.collapsible-body').stop(true, false).slideUp({
|
||||
duration: 350,
|
||||
easing: 'easeOutQuart',
|
||||
queue: false,
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$panel_headers.not(object).removeClass('active').parent().removeClass('active');
|
||||
$panel_headers.not(object).parent().children('.collapsible-body').stop(true, false).slideUp({
|
||||
duration: 350,
|
||||
easing: 'easeOutQuart',
|
||||
queue: false,
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Expandable Open
|
||||
function expandableOpen(object) {
|
||||
if (object.hasClass('active')) {
|
||||
object.parent().addClass('active');
|
||||
} else {
|
||||
object.parent().removeClass('active');
|
||||
}
|
||||
if (object.parent().hasClass('active')) {
|
||||
object.siblings('.collapsible-body').stop(true, false).slideDown({
|
||||
duration: 350,
|
||||
easing: 'easeOutQuart',
|
||||
queue: false,
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
object.siblings('.collapsible-body').stop(true, false).slideUp({
|
||||
duration: 350,
|
||||
easing: 'easeOutQuart',
|
||||
queue: false,
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if object is children of panel header
|
||||
* @param {Object} object Jquery object
|
||||
* @return {Boolean} true if it is children
|
||||
*/
|
||||
function isChildrenOfPanelHeader(object) {
|
||||
|
||||
var panelHeader = getPanelHeader(object);
|
||||
|
||||
return panelHeader.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get panel header from a children element
|
||||
* @param {Object} object Jquery object
|
||||
* @return {Object} panel header object
|
||||
*/
|
||||
function getPanelHeader(object) {
|
||||
|
||||
return object.closest('li > .collapsible-header');
|
||||
}
|
||||
|
||||
/** *** End Helper Functions *****/
|
||||
|
||||
if (options.accordion || collapsible_type === 'accordion' || collapsible_type === undefined) {
|
||||
// Handle Accordion
|
||||
// Add click handler to only direct collapsible header children
|
||||
$panel_headers = $this.find('> li > .collapsible-header');
|
||||
$panel_headers.on('click.collapse', function (e) {
|
||||
var element = $(e.target);
|
||||
|
||||
if (isChildrenOfPanelHeader(element)) {
|
||||
element = getPanelHeader(element);
|
||||
}
|
||||
|
||||
element.toggleClass('active');
|
||||
accordionOpen(element);
|
||||
});
|
||||
// Open first active
|
||||
accordionOpen($panel_headers.filter('.active').first());
|
||||
} else {
|
||||
// Handle Expandables
|
||||
$panel_headers.each(function () {
|
||||
// Add click handler to only direct collapsible header children
|
||||
$(this).on('click.collapse', function (e) {
|
||||
var element = $(e.target);
|
||||
if (isChildrenOfPanelHeader(element)) {
|
||||
element = getPanelHeader(element);
|
||||
}
|
||||
element.toggleClass('active');
|
||||
expandableOpen(element);
|
||||
});
|
||||
// Open any bodies that have the active class
|
||||
if ($(this).hasClass('active')) {
|
||||
expandableOpen($(this));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
$('.collapsible').collapsible();
|
||||
});
|
||||
})(jQuery);
|
||||
Executable
+330
@@ -0,0 +1,330 @@
|
||||
'use strict';
|
||||
|
||||
/* DROPDOWN */
|
||||
|
||||
(function ($) {
|
||||
|
||||
// Add posibility to scroll to selected option
|
||||
// usefull for select for example
|
||||
$.fn.scrollTo = function (elem) {
|
||||
$(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem).offset().top);
|
||||
return this;
|
||||
};
|
||||
|
||||
$.fn.dropdown = function (option) {
|
||||
var defaults = {
|
||||
inDuration: 300,
|
||||
outDuration: 225,
|
||||
constrain_width: true, // Constrains width of dropdown to the activator
|
||||
hover: false,
|
||||
gutter: 0, // Spacing from edge
|
||||
belowOrigin: false,
|
||||
alignment: 'left'
|
||||
};
|
||||
|
||||
this.each(function () {
|
||||
var origin = $(this);
|
||||
var options = $.extend({}, defaults, option);
|
||||
var isFocused = false;
|
||||
|
||||
// Dropdown menu
|
||||
var activates = $('#' + origin.attr('data-activates'));
|
||||
|
||||
function updateOptions() {
|
||||
if (origin.data('induration') !== undefined) {
|
||||
options.inDuration = origin.data('inDuration');
|
||||
}
|
||||
if (origin.data('outduration') !== undefined) {
|
||||
options.outDuration = origin.data('outDuration');
|
||||
}
|
||||
if (origin.data('constrainwidth') !== undefined) {
|
||||
options.constrain_width = origin.data('constrainwidth');
|
||||
}
|
||||
if (origin.data('hover') !== undefined) {
|
||||
options.hover = origin.data('hover');
|
||||
}
|
||||
if (origin.data('gutter') !== undefined) {
|
||||
options.gutter = origin.data('gutter');
|
||||
}
|
||||
if (origin.data('beloworigin') !== undefined) {
|
||||
options.belowOrigin = origin.data('beloworigin');
|
||||
}
|
||||
if (origin.data('alignment') !== undefined) {
|
||||
options.alignment = origin.data('alignment');
|
||||
}
|
||||
}
|
||||
|
||||
updateOptions();
|
||||
|
||||
// Attach dropdown to its activator
|
||||
origin.after(activates);
|
||||
|
||||
/*
|
||||
Helper function to position and resize dropdown.
|
||||
Used in hover and click handler.
|
||||
*/
|
||||
function placeDropdown(eventType) {
|
||||
// Check for simultaneous focus and click events.
|
||||
if (eventType === 'focus') {
|
||||
isFocused = true;
|
||||
}
|
||||
|
||||
// Check html data attributes
|
||||
updateOptions();
|
||||
|
||||
// Set Dropdown state
|
||||
activates.addClass('active');
|
||||
origin.addClass('active');
|
||||
|
||||
// Constrain width
|
||||
if (options.constrain_width === true) {
|
||||
activates.css('width', origin.outerWidth());
|
||||
} else {
|
||||
activates.css('white-space', 'nowrap');
|
||||
}
|
||||
|
||||
// Offscreen detection
|
||||
var windowHeight = window.innerHeight;
|
||||
var originHeight = origin.innerHeight();
|
||||
var offsetLeft = origin.offset().left;
|
||||
var offsetTop = origin.offset().top - $(window).scrollTop();
|
||||
var currAlignment = options.alignment;
|
||||
var gutterSpacing = 0;
|
||||
var leftPosition = 0;
|
||||
|
||||
// Below Origin
|
||||
var verticalOffset = 0;
|
||||
if (options.belowOrigin === true) {
|
||||
verticalOffset = originHeight;
|
||||
}
|
||||
|
||||
// Check for scrolling positioned container.
|
||||
var scrollOffset = 0;
|
||||
var wrapper = origin.parent();
|
||||
if (!wrapper.is('body') && wrapper[0].scrollHeight > wrapper[0].clientHeight) {
|
||||
scrollOffset = wrapper[0].scrollTop;
|
||||
}
|
||||
|
||||
if (offsetLeft + activates.innerWidth() > $(window).width()) {
|
||||
// Dropdown goes past screen on right, force right alignment
|
||||
currAlignment = 'right';
|
||||
} else if (offsetLeft - activates.innerWidth() + origin.innerWidth() < 0) {
|
||||
// Dropdown goes past screen on left, force left alignment
|
||||
currAlignment = 'left';
|
||||
}
|
||||
// Vertical bottom offscreen detection
|
||||
if (offsetTop + activates.innerHeight() > windowHeight) {
|
||||
// If going upwards still goes offscreen, just crop height of dropdown.
|
||||
if (offsetTop + originHeight - activates.innerHeight() < 0) {
|
||||
var adjustedHeight = windowHeight - offsetTop - verticalOffset;
|
||||
activates.css('max-height', adjustedHeight);
|
||||
} else {
|
||||
// Flow upwards.
|
||||
if (!verticalOffset) {
|
||||
verticalOffset += originHeight;
|
||||
}
|
||||
verticalOffset -= activates.innerHeight();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle edge alignment
|
||||
if (currAlignment === 'left') {
|
||||
gutterSpacing = options.gutter;
|
||||
leftPosition = origin.position().left + gutterSpacing;
|
||||
} else if (currAlignment === 'right') {
|
||||
var offsetRight = origin.position().left + origin.outerWidth() - activates.outerWidth();
|
||||
gutterSpacing = -options.gutter;
|
||||
leftPosition = offsetRight + gutterSpacing;
|
||||
}
|
||||
|
||||
// Position dropdown
|
||||
activates.css({
|
||||
position: 'absolute',
|
||||
top: origin.position().top + verticalOffset + scrollOffset,
|
||||
left: leftPosition
|
||||
});
|
||||
|
||||
// Show dropdown
|
||||
activates.stop(true, true).css('opacity', 0).slideDown({
|
||||
queue: false,
|
||||
duration: options.inDuration,
|
||||
easing: 'easeOutCubic',
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
}).animate({
|
||||
opacity: 1,
|
||||
scrollTop: 0
|
||||
}, {
|
||||
queue: false,
|
||||
duration: options.inDuration,
|
||||
easing: 'easeOutSine'
|
||||
});
|
||||
}
|
||||
|
||||
function hideDropdown() {
|
||||
// Check for simultaneous focus and click events.
|
||||
isFocused = false;
|
||||
activates.fadeOut(options.outDuration);
|
||||
activates.removeClass('active');
|
||||
origin.removeClass('active');
|
||||
setTimeout(function () {
|
||||
activates.css('max-height', '');
|
||||
}, options.outDuration);
|
||||
}
|
||||
|
||||
// Hover
|
||||
if (options.hover) {
|
||||
var open = false;
|
||||
origin.unbind('click.' + origin.attr('id'));
|
||||
// Hover handler to show dropdown
|
||||
origin.on('mouseenter', function () {
|
||||
// Mouse over
|
||||
if (open === false) {
|
||||
placeDropdown();
|
||||
open = true;
|
||||
}
|
||||
});
|
||||
origin.on('mouseleave', function (e) {
|
||||
// If hover on origin then to something other than dropdown content, then close
|
||||
var toEl = e.toElement || e.relatedTarget; // added browser compatibility for target element
|
||||
if (!$(toEl).closest('.dropdown-content').is(activates)) {
|
||||
activates.stop(true, true);
|
||||
hideDropdown();
|
||||
open = false;
|
||||
}
|
||||
});
|
||||
|
||||
activates.on('mouseleave', function (e) {
|
||||
// Mouse out
|
||||
var toEl = e.toElement || e.relatedTarget;
|
||||
if (!$(toEl).closest('.dropdown-button').is(origin)) {
|
||||
activates.stop(true, true);
|
||||
hideDropdown();
|
||||
open = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Click
|
||||
} else {
|
||||
// Click handler to show dropdown
|
||||
origin.unbind('click.' + origin.attr('id'));
|
||||
origin.bind('click.' + origin.attr('id'), function (e) {
|
||||
if (!isFocused) {
|
||||
if (origin[0] === e.currentTarget && !origin.hasClass('active') && $(e.target).closest('.dropdown-content').length === 0) {
|
||||
e.preventDefault(); // Prevents button click from moving window
|
||||
placeDropdown('click');
|
||||
}
|
||||
// If origin is clicked and menu is open, close menu
|
||||
else if (origin.hasClass('active')) {
|
||||
hideDropdown();
|
||||
$(document).unbind('click.' + activates.attr('id') + ' touchstart.' + activates.attr('id'));
|
||||
}
|
||||
// If menu open, add click close handler to document
|
||||
if (activates.hasClass('active')) {
|
||||
$(document).bind('click.' + activates.attr('id') + ' touchstart.' + activates.attr('id'), function (e) {
|
||||
if (!activates.is(e.target) && !origin.is(e.target) && !origin.find(e.target).length) {
|
||||
hideDropdown();
|
||||
$(document).unbind('click.' + activates.attr('id') + ' touchstart.' + activates.attr('id'));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} // End else
|
||||
|
||||
// Listen to open and close event - useful for select component
|
||||
origin.on('open', function (e, eventType) {
|
||||
placeDropdown(eventType);
|
||||
});
|
||||
origin.on('close', hideDropdown);
|
||||
});
|
||||
}; // End dropdown plugin
|
||||
|
||||
$(document).ready(function () {
|
||||
$('.dropdown-button').dropdown();
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
var dropdownSelectors = $('.dropdown, .dropup');
|
||||
|
||||
// Custom function to read dropdown data
|
||||
// =========================
|
||||
function dropdownEffectData(target) {
|
||||
// @todo - page level global?
|
||||
var effectInDefault = 'fadeIn';
|
||||
var effectOutDefault = 'fadeOut';
|
||||
var dropdown = $(target);
|
||||
var dropdownMenu = $('.dropdown-menu', target);
|
||||
var parentUl = dropdown.parents('ul.nav');
|
||||
|
||||
// If parent is ul.nav allow global effect settings
|
||||
if (parentUl.height > 0) {
|
||||
effectInDefault = parentUl.data('dropdown-in') || null;
|
||||
effectOutDefault = parentUl.data('dropdown-out') || null;
|
||||
}
|
||||
|
||||
return {
|
||||
target: target,
|
||||
dropdown: dropdown,
|
||||
dropdownMenu: dropdownMenu,
|
||||
effectIn: dropdownMenu.data('dropdown-in') || effectInDefault,
|
||||
effectOut: dropdownMenu.data('dropdown-out') || effectOutDefault
|
||||
};
|
||||
}
|
||||
|
||||
// Custom function to start effect (in or out)
|
||||
// =========================
|
||||
function dropdownEffectStart(data, effectToStart) {
|
||||
if (effectToStart) {
|
||||
data.dropdown.addClass('dropdown-animating');
|
||||
data.dropdownMenu.addClass('animated');
|
||||
data.dropdownMenu.addClass(effectToStart);
|
||||
}
|
||||
}
|
||||
|
||||
// Custom function to read when animation is over
|
||||
// =========================
|
||||
function dropdownEffectEnd(data, callbackFunc) {
|
||||
var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
|
||||
data.dropdown.one(animationEnd, function () {
|
||||
data.dropdown.removeClass('dropdown-animating');
|
||||
data.dropdownMenu.removeClass('animated');
|
||||
data.dropdownMenu.removeClass(data.effectIn);
|
||||
data.dropdownMenu.removeClass(data.effectOut);
|
||||
|
||||
// Custom callback option, used to remove open class in out effect
|
||||
if (typeof callbackFunc === 'function') {
|
||||
callbackFunc();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Bootstrap API hooks
|
||||
// =========================
|
||||
dropdownSelectors.on({
|
||||
'show.bs.dropdown': function showBsDropdown() {
|
||||
// On show, start in effect
|
||||
var dropdown = dropdownEffectData(this);
|
||||
dropdownEffectStart(dropdown, dropdown.effectIn);
|
||||
},
|
||||
'shown.bs.dropdown': function shownBsDropdown() {
|
||||
// On shown, remove in effect once complete
|
||||
var dropdown = dropdownEffectData(this);
|
||||
if (dropdown.effectIn && dropdown.effectOut) {
|
||||
dropdownEffectEnd(dropdown);
|
||||
}
|
||||
},
|
||||
'hide.bs.dropdown': function hideBsDropdown(e) {
|
||||
// On hide, start out effect
|
||||
var dropdown = dropdownEffectData(this);
|
||||
if (dropdown.effectOut) {
|
||||
e.preventDefault();
|
||||
dropdownEffectStart(dropdown, dropdown.effectOut);
|
||||
dropdownEffectEnd(dropdown, function () {
|
||||
dropdown.dropdown.removeClass('show');
|
||||
dropdown.dropdownMenu.removeClass('show');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Enhanced Bootstrap Modals
|
||||
https://mdbootstrap.com
|
||||
office@mdbootstrap.com
|
||||
*/
|
||||
|
||||
$('body').on('shown.bs.modal', '.modal', function() {
|
||||
if($('.modal-backdrop').length) {
|
||||
} else {
|
||||
|
||||
$modal_dialog = $(this).children('.modal-dialog')
|
||||
|
||||
if($modal_dialog.hasClass('modal-side')) {
|
||||
$(this).addClass('modal-scrolling');
|
||||
$('body').addClass('scrollable');
|
||||
}
|
||||
|
||||
if($modal_dialog.hasClass('modal-frame')) {
|
||||
$(this).addClass('modal-content-clickable');
|
||||
$('body').addClass('scrollable');
|
||||
}
|
||||
}
|
||||
});
|
||||
$('body').on('hidden.bs.modal', '.modal', function() {
|
||||
$('body').removeClass('scrollable');
|
||||
});
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
/** *****************
|
||||
* File input *
|
||||
******************/
|
||||
(function ($) {
|
||||
|
||||
$(document).on('change', '.file-field input[type="file"]', function (e) {
|
||||
|
||||
var $this = $(e.target);
|
||||
var $file_field = $this.closest('.file-field');
|
||||
var $path_input = $file_field.find('input.file-path');
|
||||
var files = $this[0].files;
|
||||
var file_names = [];
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var file_name = files[i].name;
|
||||
file_names.push(file_name);
|
||||
}
|
||||
$path_input.val(file_names.join(', '));
|
||||
$path_input.trigger('change');
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,158 @@
|
||||
/* FORMS */
|
||||
|
||||
(function ($) {
|
||||
$(document).ready(function () {
|
||||
|
||||
// Function to update labels of text fields
|
||||
Materialize.updateTextFields = function () {
|
||||
var input_selector = 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea';
|
||||
$(input_selector).each(function (index, element) {
|
||||
if ($(element).val().length > 0 || $(this).attr('placeholder') !== undefined || $(element)[0].validity.badInput === true) {
|
||||
$(this).siblings('label, i').addClass('active');
|
||||
} else {
|
||||
$(this).siblings('label, i').removeClass('active');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Text based inputs
|
||||
var input_selector = 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea';
|
||||
|
||||
// Handle HTML5 autofocus
|
||||
$('input[autofocus]').siblings('label, i').addClass('active');
|
||||
|
||||
// Add active if form auto complete
|
||||
$(document).on('change', input_selector, function () {
|
||||
if ($(this).val().length !== 0 || $(this).attr('placeholder') !== undefined) {
|
||||
$(this).siblings('label, i').addClass('active');
|
||||
}
|
||||
validate_field($(this));
|
||||
});
|
||||
|
||||
// Add active if input element has been pre-populated on document ready
|
||||
$(document).ready(function () {
|
||||
Materialize.updateTextFields();
|
||||
});
|
||||
|
||||
// HTML DOM FORM RESET handling
|
||||
$(document).on('reset', function (e) {
|
||||
var formReset = $(e.target);
|
||||
if (formReset.is('form')) {
|
||||
formReset.find(input_selector).removeClass('valid').removeClass('invalid');
|
||||
formReset.find(input_selector).each(function () {
|
||||
if ($(this).attr('value') === '') {
|
||||
$(this).siblings('label, i').removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Reset select
|
||||
formReset.find('select.initialized').each(function () {
|
||||
var reset_text = formReset.find('option[selected]').text();
|
||||
formReset.siblings('input.select-dropdown').val(reset_text);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Add active when element has focus
|
||||
$(document).on('focus', input_selector, function () {
|
||||
$(this).siblings('label, i').addClass('active');
|
||||
});
|
||||
|
||||
$(document).on('blur', input_selector, function () {
|
||||
var $inputElement = $(this);
|
||||
if ($inputElement.val().length === 0 && $inputElement[0].validity.badInput !== true && $inputElement.attr('placeholder') === undefined) {
|
||||
$inputElement.siblings('label, i').removeClass('active');
|
||||
}
|
||||
validate_field($inputElement);
|
||||
});
|
||||
|
||||
validate_field = function (object) {
|
||||
var hasLength = object.attr('length') !== undefined;
|
||||
var lenAttr = parseInt(object.attr('length'));
|
||||
var len = object.val().length;
|
||||
|
||||
if (object.val().length === 0 && object[0].validity.badInput === false) {
|
||||
if (object.hasClass('validate')) {
|
||||
object.removeClass('valid');
|
||||
object.removeClass('invalid');
|
||||
}
|
||||
} else {
|
||||
if (object.hasClass('validate')) {
|
||||
// Check for character counter attributes
|
||||
if ((object.is(':valid') && hasLength && (len < lenAttr)) || (object.is(':valid') && !hasLength)) {
|
||||
object.removeClass('invalid');
|
||||
object.addClass('valid');
|
||||
} else {
|
||||
object.removeClass('valid');
|
||||
object.addClass('invalid');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Textarea Auto Resize
|
||||
var hiddenDiv = $('.hiddendiv').first();
|
||||
if (!hiddenDiv.length) {
|
||||
hiddenDiv = $('<div class="hiddendiv common"></div>');
|
||||
$('body').append(hiddenDiv);
|
||||
}
|
||||
var text_area_selector = '.materialize-textarea';
|
||||
|
||||
function textareaAutoResize($textarea) {
|
||||
// Set font properties of hiddenDiv
|
||||
|
||||
var fontFamily = $textarea.css('font-family');
|
||||
var fontSize = $textarea.css('font-size');
|
||||
|
||||
if (fontSize) {
|
||||
hiddenDiv.css('font-size', fontSize);
|
||||
}
|
||||
if (fontFamily) {
|
||||
hiddenDiv.css('font-family', fontFamily);
|
||||
}
|
||||
|
||||
if ($textarea.attr('wrap') === "off") {
|
||||
hiddenDiv.css('overflow-wrap', "normal")
|
||||
.css('white-space', "pre");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
hiddenDiv.text($textarea.val() + '\n');
|
||||
var content = hiddenDiv.html().replace(/\n/g, '<br>');
|
||||
hiddenDiv.html(content);
|
||||
|
||||
|
||||
// When textarea is hidden, width goes crazy.
|
||||
// Approximate with half of window size
|
||||
|
||||
if ($textarea.is(':visible')) {
|
||||
hiddenDiv.css('width', $textarea.width());
|
||||
} else {
|
||||
hiddenDiv.css('width', $(window).width() / 2);
|
||||
}
|
||||
|
||||
$textarea.css('height', hiddenDiv.height());
|
||||
}
|
||||
|
||||
$(text_area_selector).each(function () {
|
||||
var $textarea = $(this);
|
||||
if ($textarea.val().length) {
|
||||
textareaAutoResize($textarea);
|
||||
}
|
||||
});
|
||||
|
||||
$('body').on('keyup keydown', text_area_selector, function () {
|
||||
textareaAutoResize($(this));
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}); // End of $(document).ready
|
||||
|
||||
}(jQuery));
|
||||
Executable
+153
@@ -0,0 +1,153 @@
|
||||
'use strict';
|
||||
|
||||
/* FORMS */
|
||||
(function ($) {
|
||||
$(document).ready(function () {
|
||||
|
||||
// Text based inputs
|
||||
var input_selector = ['text', 'password', 'email', 'url', 'tel', 'number', 'search', 'search-md'].map(function (selector) {
|
||||
return 'input[type=' + selector + ']';
|
||||
}).join(', ') + ', textarea';
|
||||
|
||||
var text_area_selector = '.materialize-textarea';
|
||||
|
||||
var update_text_fields = function update_text_fields($input) {
|
||||
|
||||
var $labelAndIcon = $input.siblings('label, i');
|
||||
var hasValue = $input.val().length;
|
||||
var hasPlaceholder = $input.attr('placeholder');
|
||||
// let isValid = $input.validity.badInput === true;
|
||||
var addOrRemove = (hasValue || hasPlaceholder ? 'add' : 'remove') + 'Class';
|
||||
|
||||
$labelAndIcon[addOrRemove]('active');
|
||||
};
|
||||
|
||||
var validate_field = function validate_field($input) {
|
||||
|
||||
if ($input.hasClass('validate')) {
|
||||
var value = $input.val();
|
||||
var noValue = !value.length;
|
||||
var isValid = !$input[0].validity.badInput;
|
||||
|
||||
if (noValue && isValid) {
|
||||
$input.removeClass('valid').removeClass('invalid');
|
||||
} else {
|
||||
var valid = $input.is(':valid');
|
||||
var length = Number($input.attr('length')) || 0;
|
||||
|
||||
if (valid && (!length || length > value.length)) {
|
||||
$input.removeClass('invalid').addClass('valid');
|
||||
} else {
|
||||
$input.removeClass('valid').addClass('invalid');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var textarea_auto_resize = function textarea_auto_resize() {
|
||||
|
||||
var $textarea = $(undefined);
|
||||
if ($textarea.val().length) {
|
||||
var _$hiddenDiv = $('.hiddendiv');
|
||||
var fontFamily = $textarea.css('font-family');
|
||||
var fontSize = $textarea.css('font-size');
|
||||
|
||||
if (fontSize) {
|
||||
_$hiddenDiv.css('font-size', fontSize);
|
||||
}
|
||||
if (fontFamily) {
|
||||
_$hiddenDiv.css('font-family', fontFamily);
|
||||
}
|
||||
if ($textarea.attr('wrap') === 'off') {
|
||||
_$hiddenDiv.css('overflow-wrap', 'normal').css('white-space', 'pre');
|
||||
}
|
||||
|
||||
_$hiddenDiv.text($textarea.val() + '\n');
|
||||
var content = _$hiddenDiv.html().replace(/\n/g, '<br>');
|
||||
_$hiddenDiv.html(content);
|
||||
|
||||
// When textarea is hidden, width goes crazy.
|
||||
// Approximate with half of window size
|
||||
_$hiddenDiv.css('width', $textarea.is(':visible') ? $textarea.width() : $(window).width() / 2);
|
||||
$textarea.css('height', _$hiddenDiv.height());
|
||||
}
|
||||
};
|
||||
|
||||
// Set active on labels and icons (DOM ready scope);
|
||||
$(input_selector).each(function (index, input) {
|
||||
var $this = $(input);
|
||||
var $labelAndIcon = $this.siblings('label, i');
|
||||
update_text_fields($this);
|
||||
var isValid = input.validity.badInput; // pure js
|
||||
if (isValid) {
|
||||
$labelAndIcon.addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Add active when element has focus
|
||||
$(document).on('focus', input_selector, function (e) {
|
||||
$(e.target).siblings('label, i').addClass('active');
|
||||
});
|
||||
|
||||
// Remove active on blur when not needed or invalid
|
||||
$(document).on('blur', input_selector, function (e) {
|
||||
var $this = $(e.target);
|
||||
var noValue = !$this.val();
|
||||
var invalid = !e.target.validity.badInput;
|
||||
var noPlaceholder = $this.attr('placeholder') === undefined;
|
||||
|
||||
if (noValue && invalid && noPlaceholder) {
|
||||
$this.siblings('label, i').removeClass('active');
|
||||
}
|
||||
|
||||
validate_field($this);
|
||||
});
|
||||
|
||||
// Add active if form auto complete
|
||||
$(document).on('change', input_selector, function (e) {
|
||||
var $this = $(e.target);
|
||||
update_text_fields($this);
|
||||
validate_field($this);
|
||||
});
|
||||
|
||||
// Handle HTML5 autofocus
|
||||
$('input[autofocus]').siblings('label, i').addClass('active');
|
||||
|
||||
// HTML form reset
|
||||
$(document).on('reset', function (e) {
|
||||
var $formReset = $(e.target);
|
||||
if ($formReset.is('form')) {
|
||||
|
||||
var $formInputs = $formReset.find(input_selector);
|
||||
// Reset inputs
|
||||
$formInputs.removeClass('valid').removeClass('invalid').each(function (index, input) {
|
||||
var $this = $(input);
|
||||
var noDefaultValue = !$this.val();
|
||||
var noPlaceholder = !$this.attr('placeholder');
|
||||
if (noDefaultValue && noPlaceholder) {
|
||||
$this.siblings('label, i').removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Reset select
|
||||
$formReset.find('select.initialized').each(function (index, select) {
|
||||
var $select = $(select);
|
||||
var $visible_input = $select.siblings('input.select-dropdown');
|
||||
var default_value = $select.children('[selected]').val();
|
||||
|
||||
$select.val(default_value);
|
||||
$visible_input.val(default_value);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Textarea Auto Resize
|
||||
if (!$('.hiddendiv').first().length) {
|
||||
$hiddenDiv = $('<div class="hiddendiv common"></div>');
|
||||
$('body').append($hiddenDiv);
|
||||
}
|
||||
|
||||
$(text_area_selector).each(textarea_auto_resize);
|
||||
$('body').on('keyup keydown', text_area_selector, textarea_auto_resize);
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,580 @@
|
||||
/* FORMS */
|
||||
|
||||
;(function ($) {
|
||||
$(document).ready(function () {
|
||||
|
||||
// Function to update labels of text fields
|
||||
Materialize.updateTextFields = function () {
|
||||
var input_selector = 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea'
|
||||
$(input_selector).each(function (index, element) {
|
||||
if ($(element).val().length > 0 || element.autofocus || $(this).attr('placeholder') !== undefined || $(element)[0].validity.badInput === true) {
|
||||
$(this).siblings('label, i').addClass('active')
|
||||
}else {
|
||||
$(this).siblings('label, i').removeClass('active')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Text based inputs
|
||||
var input_selector = 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea'
|
||||
|
||||
// Add active if form auto complete
|
||||
$(document).on('change', input_selector, function () {
|
||||
if ($(this).val().length !== 0 || $(this).attr('placeholder') !== undefined) {
|
||||
$(this).siblings('label').addClass('active')
|
||||
}
|
||||
validate_field($(this))
|
||||
})
|
||||
|
||||
// Add active if input element has been pre-populated on document ready
|
||||
$(document).ready(function () {
|
||||
Materialize.updateTextFields()
|
||||
})
|
||||
|
||||
// HTML DOM FORM RESET handling
|
||||
$(document).on('reset', function (e) {
|
||||
var formReset = $(e.target)
|
||||
if (formReset.is('form')) {
|
||||
formReset.find(input_selector).removeClass('valid').removeClass('invalid')
|
||||
formReset.find(input_selector).each(function () {
|
||||
if ($(this).attr('value') === '') {
|
||||
$(this).siblings('label, i').removeClass('active')
|
||||
}
|
||||
})
|
||||
|
||||
// Reset select
|
||||
formReset.find('select.initialized').each(function () {
|
||||
var reset_text = formReset.find('option[selected]').text()
|
||||
formReset.siblings('input.select-dropdown').val(reset_text)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Add active when element has focus
|
||||
$(document).on('focus', input_selector, function () {
|
||||
$(this).siblings('label, i').addClass('active')
|
||||
})
|
||||
|
||||
$(document).on('blur', input_selector, function () {
|
||||
var $inputElement = $(this)
|
||||
if ($inputElement.val().length === 0 && $inputElement[0].validity.badInput !== true && $inputElement.attr('placeholder') === undefined) {
|
||||
$inputElement.siblings('label, i').removeClass('active')
|
||||
}
|
||||
|
||||
if ($inputElement.val().length === 0 && $inputElement[0].validity.badInput !== true && $inputElement.attr('placeholder') !== undefined) {
|
||||
$inputElement.siblings('i').removeClass('active')
|
||||
}
|
||||
validate_field($inputElement)
|
||||
})
|
||||
|
||||
window.validate_field = function (object) {
|
||||
var hasLength = object.attr('length') !== undefined
|
||||
var lenAttr = parseInt(object.attr('length'))
|
||||
var len = object.val().length
|
||||
|
||||
if (object.val().length === 0 && object[0].validity.badInput === false) {
|
||||
if (object.hasClass('validate')) {
|
||||
object.removeClass('valid')
|
||||
object.removeClass('invalid')
|
||||
}
|
||||
}else {
|
||||
if (object.hasClass('validate')) {
|
||||
// Check for character counter attributes
|
||||
if ((object.is(':valid') && hasLength && (len <= lenAttr)) || (object.is(':valid') && !hasLength)) {
|
||||
object.removeClass('invalid')
|
||||
object.addClass('valid')
|
||||
}else {
|
||||
object.removeClass('valid')
|
||||
object.addClass('invalid')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Textarea Auto Resize
|
||||
var hiddenDiv = $('.hiddendiv').first()
|
||||
if (!hiddenDiv.length) {
|
||||
hiddenDiv = $('<div class="hiddendiv common"></div>')
|
||||
$('body').append(hiddenDiv)
|
||||
}
|
||||
var text_area_selector = '.materialize-textarea'
|
||||
|
||||
function textareaAutoResize ($textarea) {
|
||||
// Set font properties of hiddenDiv
|
||||
|
||||
var fontFamily = $textarea.css('font-family')
|
||||
var fontSize = $textarea.css('font-size')
|
||||
|
||||
if (fontSize) { hiddenDiv.css('font-size', fontSize); }
|
||||
if (fontFamily) { hiddenDiv.css('font-family', fontFamily); }
|
||||
|
||||
if ($textarea.attr('wrap') === 'off') {
|
||||
hiddenDiv.css('overflow-wrap', 'normal')
|
||||
.css('white-space', 'pre')
|
||||
}
|
||||
|
||||
hiddenDiv.text($textarea.val() + '\n')
|
||||
var content = hiddenDiv.html().replace(/\n/g, '<br>')
|
||||
hiddenDiv.html(content)
|
||||
|
||||
// When textarea is hidden, width goes crazy.
|
||||
// Approximate with half of window size
|
||||
|
||||
if ($textarea.is(':visible')) {
|
||||
hiddenDiv.css('width', $textarea.width())
|
||||
}else {
|
||||
hiddenDiv.css('width', $(window).width() / 2)
|
||||
}
|
||||
|
||||
$textarea.css('height', hiddenDiv.height())
|
||||
}
|
||||
|
||||
$(text_area_selector).each(function () {
|
||||
var $textarea = $(this)
|
||||
if ($textarea.val().length) {
|
||||
textareaAutoResize($textarea)
|
||||
}
|
||||
})
|
||||
|
||||
$('body').on('keyup keydown autoresize', text_area_selector, function () {
|
||||
textareaAutoResize($(this))
|
||||
})
|
||||
|
||||
// File Input Path
|
||||
$(document).on('change', '.file-field input[type="file"]', function () {
|
||||
var file_field = $(this).closest('.file-field')
|
||||
var path_input = file_field.find('input.file-path')
|
||||
var files = $(this)[0].files
|
||||
var file_names = []
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
file_names.push(files[i].name)
|
||||
}
|
||||
path_input.val(file_names.join(', '))
|
||||
path_input.trigger('change')
|
||||
})
|
||||
|
||||
/****************
|
||||
* Range Input *
|
||||
****************/
|
||||
|
||||
var range_type = 'input[type=range]'
|
||||
var range_mousedown = false
|
||||
var left
|
||||
|
||||
$(range_type).each(function () {
|
||||
var thumb = $('<span class="thumb"><span class="value"></span></span>')
|
||||
$(this).after(thumb)
|
||||
})
|
||||
|
||||
var range_wrapper = '.range-field'
|
||||
$(document).on('change', range_type, function (e) {
|
||||
var thumb = $(this).siblings('.thumb')
|
||||
thumb.find('.value').html($(this).val())
|
||||
})
|
||||
|
||||
$(document).on('input mousedown touchstart', range_type, function (e) {
|
||||
var thumb = $(this).siblings('.thumb')
|
||||
var width = $(this).outerWidth()
|
||||
|
||||
// If thumb indicator does not exist yet, create it
|
||||
if (thumb.length <= 0) {
|
||||
thumb = $('<span class="thumb"><span class="value"></span></span>')
|
||||
$(this).after(thumb)
|
||||
}
|
||||
|
||||
// Set indicator value
|
||||
thumb.find('.value').html($(this).val())
|
||||
|
||||
range_mousedown = true
|
||||
$(this).addClass('active')
|
||||
|
||||
if (!thumb.hasClass('active')) {
|
||||
thumb.velocity({ height: '30px', width: '30px', top: '-20px', marginLeft: '-15px'}, { duration: 300, easing: 'easeOutExpo' })
|
||||
}
|
||||
|
||||
if (e.type !== 'input') {
|
||||
if (e.pageX === undefined || e.pageX === null) { // mobile
|
||||
left = e.originalEvent.touches[0].pageX - $(this).offset().left
|
||||
}else { // desktop
|
||||
left = e.pageX - $(this).offset().left
|
||||
}
|
||||
if (left < 0) {
|
||||
left = 0
|
||||
}
|
||||
else if (left > width) {
|
||||
left = width
|
||||
}
|
||||
thumb.addClass('active').css('left', left)
|
||||
}
|
||||
|
||||
thumb.find('.value').html($(this).val())
|
||||
})
|
||||
|
||||
$(document).on('mouseup touchend', range_wrapper, function () {
|
||||
range_mousedown = false
|
||||
$(this).removeClass('active')
|
||||
})
|
||||
|
||||
$(document).on('mousemove touchmove', range_wrapper, function (e) {
|
||||
var thumb = $(this).children('.thumb')
|
||||
var left
|
||||
if (range_mousedown) {
|
||||
if (!thumb.hasClass('active')) {
|
||||
thumb.velocity({ height: '30px', width: '30px', top: '-20px', marginLeft: '-15px'}, { duration: 300, easing: 'easeOutExpo' })
|
||||
}
|
||||
if (e.pageX === undefined || e.pageX === null) { // mobile
|
||||
left = e.originalEvent.touches[0].pageX - $(this).offset().left
|
||||
}else { // desktop
|
||||
left = e.pageX - $(this).offset().left
|
||||
}
|
||||
var width = $(this).outerWidth()
|
||||
|
||||
if (left < 0) {
|
||||
left = 0
|
||||
}
|
||||
else if (left > width) {
|
||||
left = width
|
||||
}
|
||||
thumb.addClass('active').css('left', left)
|
||||
thumb.find('.value').html(thumb.siblings(range_type).val())
|
||||
}
|
||||
})
|
||||
|
||||
$(document).on('mouseout touchleave', range_wrapper, function () {
|
||||
if (!range_mousedown) {
|
||||
var thumb = $(this).children('.thumb')
|
||||
|
||||
if (thumb.hasClass('active')) {
|
||||
thumb.velocity({ height: '0', width: '0', top: '10px', marginLeft: '-6px'}, { duration: 100 })
|
||||
}
|
||||
thumb.removeClass('active')
|
||||
}
|
||||
})
|
||||
}); // End of $(document).ready
|
||||
|
||||
/*******************
|
||||
* Select Plugin *
|
||||
******************/
|
||||
$.fn.material_select = function (callback) {
|
||||
$(this).each(function () {
|
||||
var $select = $(this)
|
||||
|
||||
if ($select.hasClass('browser-default')) {
|
||||
return; // Continue to next (return false breaks out of entire loop)
|
||||
}
|
||||
|
||||
var multiple = $select.attr('multiple') ? true : false,
|
||||
lastID = $select.data('select-id') // Tear down structure if Select needs to be rebuilt
|
||||
|
||||
if (lastID) {
|
||||
$select.parent().find('span.caret').remove()
|
||||
$select.parent().find('input').remove()
|
||||
|
||||
$select.unwrap()
|
||||
$('ul#select-options-' + lastID).remove()
|
||||
}
|
||||
|
||||
// If destroying the select, remove the selelct-id and reset it to it's uninitialized state.
|
||||
if (callback === 'destroy') {
|
||||
$select.data('select-id', null).removeClass('initialized')
|
||||
return
|
||||
}
|
||||
|
||||
var uniqueID = Materialize.guid()
|
||||
$select.data('select-id', uniqueID)
|
||||
var wrapper = $('<div class="select-wrapper"></div>')
|
||||
wrapper.addClass($select.attr('class'))
|
||||
var options = $('<ul id="select-options-' + uniqueID + '" class="dropdown-content select-dropdown ' + (multiple ? 'multiple-select-dropdown' : '') + '"></ul>'),
|
||||
selectChildren = $select.children('option, optgroup'),
|
||||
valuesSelected = [],
|
||||
optionsHover = false
|
||||
|
||||
var label = $select.find('option:selected').html() || $select.find('option:first').html() || ''
|
||||
|
||||
// Function that renders and appends the option taking into
|
||||
// account type and possible image icon.
|
||||
var appendOptionWithIcon = function (select, option, type) {
|
||||
// Add disabled attr if disabled
|
||||
var disabledClass = (option.is(':disabled')) ? 'disabled ' : ''
|
||||
|
||||
// add icons
|
||||
var icon_url = option.data('icon')
|
||||
var classes = option.attr('class')
|
||||
if (!!icon_url) {
|
||||
var classString = ''
|
||||
if (!!classes) classString = ' class="' + classes + '"'
|
||||
|
||||
// Check for multiple type.
|
||||
if (type === 'multiple') {
|
||||
options.append($('<li class="' + disabledClass + '"><img src="' + icon_url + '"' + classString + '><span><input type="checkbox"' + disabledClass + '/><label></label>' + option.html() + '</span></li>'))
|
||||
} else {
|
||||
options.append($('<li class="' + disabledClass + '"><img src="' + icon_url + '"' + classString + '><span>' + option.html() + '</span></li>'))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Check for multiple type.
|
||||
if (type === 'multiple') {
|
||||
options.append($('<li class="' + disabledClass + '"><span><input type="checkbox"' + disabledClass + '/><label></label>' + option.html() + '</span></li>'))
|
||||
} else {
|
||||
options.append($('<li class="' + disabledClass + '"><span>' + option.html() + '</span></li>'))
|
||||
}
|
||||
}
|
||||
|
||||
/* Create dropdown structure. */
|
||||
if (selectChildren.length) {
|
||||
selectChildren.each(function () {
|
||||
if ($(this).is('option')) {
|
||||
// Direct descendant option.
|
||||
if (multiple) {
|
||||
appendOptionWithIcon($select, $(this), 'multiple')
|
||||
} else {
|
||||
appendOptionWithIcon($select, $(this))
|
||||
}
|
||||
} else if ($(this).is('optgroup')) {
|
||||
// Optgroup.
|
||||
var selectOptions = $(this).children('option')
|
||||
options.append($('<li class="optgroup"><span>' + $(this).attr('label') + '</span></li>'))
|
||||
|
||||
selectOptions.each(function () {
|
||||
appendOptionWithIcon($select, $(this))
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
options.find('li:not(.optgroup)').each(function (i) {
|
||||
$(this).click(function (e) {
|
||||
// Check if option element is disabled
|
||||
if (!$(this).hasClass('disabled') && !$(this).hasClass('optgroup')) {
|
||||
var selected = true
|
||||
|
||||
if (multiple) {
|
||||
$('input[type="checkbox"]', this).prop('checked', function (i, v) { return !v; })
|
||||
selected = toggleEntryFromArray(valuesSelected, $(this).index(), $select)
|
||||
$newSelect.trigger('focus')
|
||||
} else {
|
||||
options.find('li').removeClass('active')
|
||||
$(this).toggleClass('active')
|
||||
$newSelect.val($(this).text())
|
||||
}
|
||||
|
||||
activateOption(options, $(this))
|
||||
$select.find('option').eq(i).prop('selected', selected)
|
||||
// Trigger onchange() event
|
||||
$select.trigger('change')
|
||||
if (typeof callback !== 'undefined') callback()
|
||||
}
|
||||
|
||||
e.stopPropagation()
|
||||
})
|
||||
})
|
||||
|
||||
// Wrap Elements
|
||||
$select.wrap(wrapper)
|
||||
// Add Select Display Element
|
||||
var dropdownIcon = $('<span class="caret">▼</span>')
|
||||
if ($select.is(':disabled'))
|
||||
dropdownIcon.addClass('disabled')
|
||||
|
||||
// escape double quotes
|
||||
var sanitizedLabelHtml = label.replace(/"/g, '"')
|
||||
|
||||
var $newSelect = $('<input type="text" class="select-dropdown" readonly="true" ' + (($select.is(':disabled')) ? 'disabled' : '') + ' data-activates="select-options-' + uniqueID + '" value="' + sanitizedLabelHtml + '"/>')
|
||||
$select.before($newSelect)
|
||||
$newSelect.before(dropdownIcon)
|
||||
|
||||
$newSelect.after(options)
|
||||
// Check if section element is disabled
|
||||
if (!$select.is(':disabled')) {
|
||||
$newSelect.dropdown({'hover': false, 'closeOnClick': false})
|
||||
}
|
||||
|
||||
// Copy tabindex
|
||||
if ($select.attr('tabindex')) {
|
||||
$($newSelect[0]).attr('tabindex', $select.attr('tabindex'))
|
||||
}
|
||||
|
||||
$select.addClass('initialized')
|
||||
|
||||
$newSelect.on({
|
||||
'focus': function () {
|
||||
if ($('ul.select-dropdown').not(options[0]).is(':visible')) {
|
||||
$('input.select-dropdown').trigger('close')
|
||||
}
|
||||
if (!options.is(':visible')) {
|
||||
$(this).trigger('open', ['focus'])
|
||||
var label = $(this).val()
|
||||
var selectedOption = options.find('li').filter(function () {
|
||||
return $(this).text().toLowerCase() === label.toLowerCase()
|
||||
})[0]
|
||||
activateOption(options, selectedOption)
|
||||
}
|
||||
},
|
||||
'touchend click': function (e) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
})
|
||||
|
||||
$newSelect.on('blur', function () {
|
||||
if (!multiple) {
|
||||
$(this).trigger('close')
|
||||
}
|
||||
options.find('li.selected').removeClass('selected')
|
||||
})
|
||||
|
||||
options.hover(function () {
|
||||
optionsHover = true
|
||||
}, function () {
|
||||
optionsHover = false
|
||||
})
|
||||
|
||||
$(window).on({
|
||||
'click': function () {
|
||||
multiple && (optionsHover || $newSelect.trigger('close'))
|
||||
}
|
||||
})
|
||||
|
||||
// Add initial multiple selections.
|
||||
if (multiple) {
|
||||
$select.find('option:selected:not(:disabled)').each(function () {
|
||||
var index = $(this).index()
|
||||
|
||||
toggleEntryFromArray(valuesSelected, index, $select)
|
||||
options.find('li').eq(index).find(':checkbox').prop('checked', true)
|
||||
})
|
||||
}
|
||||
|
||||
// Make option as selected and scroll to selected position
|
||||
activateOption = function (collection, newOption) {
|
||||
if (newOption) {
|
||||
collection.find('li.selected').removeClass('selected')
|
||||
var option = $(newOption)
|
||||
option.addClass('selected')
|
||||
options.scrollTo(option)
|
||||
}
|
||||
}
|
||||
|
||||
// Allow user to search by typing
|
||||
// this array is cleared after 1 second
|
||||
var filterQuery = [],
|
||||
onKeyDown = function (e) {
|
||||
// TAB - switch to another input
|
||||
if (e.which == 9) {
|
||||
$newSelect.trigger('close')
|
||||
return
|
||||
}
|
||||
|
||||
// ARROW DOWN WHEN SELECT IS CLOSED - open select options
|
||||
if (e.which == 40 && !options.is(':visible')) {
|
||||
$newSelect.trigger('open')
|
||||
return
|
||||
}
|
||||
|
||||
// ENTER WHEN SELECT IS CLOSED - submit form
|
||||
if (e.which == 13 && !options.is(':visible')) {
|
||||
return
|
||||
}
|
||||
|
||||
e.preventDefault()
|
||||
|
||||
// CASE WHEN USER TYPE LETTERS
|
||||
var letter = String.fromCharCode(e.which).toLowerCase(),
|
||||
nonLetters = [9, 13, 27, 38, 40]
|
||||
if (letter && (nonLetters.indexOf(e.which) === -1)) {
|
||||
filterQuery.push(letter)
|
||||
|
||||
var string = filterQuery.join(''),
|
||||
newOption = options.find('li').filter(function () {
|
||||
return $(this).text().toLowerCase().indexOf(string) === 0
|
||||
})[0]
|
||||
|
||||
if (newOption) {
|
||||
activateOption(options, newOption)
|
||||
}
|
||||
}
|
||||
|
||||
// ENTER - select option and close when select options are opened
|
||||
if (e.which == 13) {
|
||||
var activeOption = options.find('li.selected:not(.disabled)')[0]
|
||||
if (activeOption) {
|
||||
$(activeOption).trigger('click')
|
||||
if (!multiple) {
|
||||
$newSelect.trigger('close')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ARROW DOWN - move to next not disabled option
|
||||
if (e.which == 40) {
|
||||
if (options.find('li.selected').length) {
|
||||
newOption = options.find('li.selected').next('li:not(.disabled)')[0]
|
||||
} else {
|
||||
newOption = options.find('li:not(.disabled)')[0]
|
||||
}
|
||||
activateOption(options, newOption)
|
||||
}
|
||||
|
||||
// ESC - close options
|
||||
if (e.which == 27) {
|
||||
$newSelect.trigger('close')
|
||||
}
|
||||
|
||||
// ARROW UP - move to previous not disabled option
|
||||
if (e.which == 38) {
|
||||
newOption = options.find('li.selected').prev('li:not(.disabled)')[0]
|
||||
if (newOption)
|
||||
activateOption(options, newOption)
|
||||
}
|
||||
|
||||
// Automaticaly clean filter query so user can search again by starting letters
|
||||
setTimeout(function () { filterQuery = []; }, 1000)
|
||||
}
|
||||
|
||||
$newSelect.on('keydown', onKeyDown)
|
||||
})
|
||||
|
||||
function toggleEntryFromArray (entriesArray, entryIndex, select) {
|
||||
var index = entriesArray.indexOf(entryIndex),
|
||||
notAdded = index === -1
|
||||
|
||||
if (notAdded) {
|
||||
entriesArray.push(entryIndex)
|
||||
} else {
|
||||
entriesArray.splice(index, 1)
|
||||
}
|
||||
|
||||
select.siblings('ul.dropdown-content').find('li').eq(entryIndex).toggleClass('active')
|
||||
|
||||
// use notAdded instead of true (to detect if the option is selected or not)
|
||||
select.find('option').eq(entryIndex).prop('selected', notAdded)
|
||||
setValueToInput(entriesArray, select)
|
||||
|
||||
return notAdded
|
||||
}
|
||||
|
||||
function setValueToInput (entriesArray, select) {
|
||||
var value = ''
|
||||
|
||||
for (var i = 0, count = entriesArray.length; i < count; i++) {
|
||||
var text = select.find('option').eq(entriesArray[i]).text()
|
||||
|
||||
i === 0 ? value += text : value += ', ' + text
|
||||
}
|
||||
|
||||
if (value === '') {
|
||||
value = select.find('option:disabled').eq(0).text()
|
||||
}
|
||||
|
||||
select.siblings('input.select-dropdown').val(value)
|
||||
}
|
||||
}
|
||||
}(jQuery));
|
||||
|
||||
jQuery('select').siblings('input.select-dropdown').on('mousedown', function (e) {
|
||||
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
|
||||
if (e.clientX >= e.target.clientWidth || e.clientY >= e.target.clientHeight) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
// Required for Meteor package, the use of window prevents export by Meteor
|
||||
(function(window){
|
||||
if(window.Package){
|
||||
Materialize = {};
|
||||
} else {
|
||||
window.Materialize = {};
|
||||
}
|
||||
})(window);
|
||||
|
||||
|
||||
// Unique ID
|
||||
Materialize.guid = (function() {
|
||||
function s4() {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
return function() {
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
|
||||
s4() + '-' + s4() + s4() + s4();
|
||||
};
|
||||
})();
|
||||
|
||||
Materialize.elementOrParentIsFixed = function(element) {
|
||||
var $element = $(element);
|
||||
var $checkElements = $element.add($element.parents());
|
||||
var isFixed = false;
|
||||
$checkElements.each(function(){
|
||||
if ($(this).css("position") === "fixed") {
|
||||
isFixed = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return isFixed;
|
||||
};
|
||||
|
||||
// Velocity has conflicts when loaded with jQuery, this will check for it
|
||||
var Vel;
|
||||
if ($) {
|
||||
Vel = $.Velocity;
|
||||
} else if (jQuery) {
|
||||
Vel = jQuery.Velocity;
|
||||
} else {
|
||||
Vel = Velocity;
|
||||
}
|
||||
Executable
+2643
File diff suppressed because it is too large
Load Diff
Executable
+799
@@ -0,0 +1,799 @@
|
||||
/*!
|
||||
* Name : Video Worker (wrapper for Youtube, Vimeo and Local videos)
|
||||
* Version : 1.2.1
|
||||
* Author : _nK https://nkdev.info
|
||||
* GitHub : https://github.com/nk-o/jarallax
|
||||
*/
|
||||
(function (window) {
|
||||
'use strict';
|
||||
|
||||
// Extend like jQuery.extend
|
||||
function extend (out) {
|
||||
out = out || {};
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
if (!arguments[i]) {
|
||||
continue;
|
||||
}
|
||||
for (var key in arguments[i]) {
|
||||
if (arguments[i].hasOwnProperty(key)) {
|
||||
out[key] = arguments[i][key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Deferred
|
||||
// thanks http://stackoverflow.com/questions/18096715/implement-deferred-object-without-using-jquery
|
||||
function Deferred () {
|
||||
this._done = [];
|
||||
this._fail = [];
|
||||
}
|
||||
Deferred.prototype = {
|
||||
execute: function (list, args) {
|
||||
var i = list.length;
|
||||
args = Array.prototype.slice.call(args);
|
||||
while(i--) {
|
||||
list[i].apply(null, args);
|
||||
}
|
||||
},
|
||||
resolve: function () {
|
||||
this.execute(this._done, arguments);
|
||||
},
|
||||
reject: function () {
|
||||
this.execute(this._fail, arguments);
|
||||
},
|
||||
done: function (callback) {
|
||||
this._done.push(callback);
|
||||
},
|
||||
fail: function (callback) {
|
||||
this._fail.push(callback);
|
||||
}
|
||||
};
|
||||
|
||||
// init events
|
||||
function addEventListener (el, eventName, handler) {
|
||||
if (el.addEventListener) {
|
||||
el.addEventListener(eventName, handler);
|
||||
} else {
|
||||
el.attachEvent('on' + eventName, function (){
|
||||
handler.call(el);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var VideoWorker = (function () {
|
||||
var ID = 0;
|
||||
|
||||
function VideoWorker_inner (url, options) {
|
||||
var _this = this;
|
||||
|
||||
_this.url = url;
|
||||
|
||||
_this.options_default = {
|
||||
autoplay: 1,
|
||||
loop: 1,
|
||||
mute: 1,
|
||||
controls: 0,
|
||||
|
||||
// start / end video time in ms
|
||||
startTime: 0,
|
||||
endTime: 0
|
||||
};
|
||||
|
||||
_this.options = extend({}, _this.options_default, options);
|
||||
|
||||
// check URL
|
||||
_this.videoID = _this.parseURL(url);
|
||||
|
||||
// init
|
||||
if(_this.videoID) {
|
||||
_this.ID = ID++;
|
||||
_this.loadAPI();
|
||||
_this.init();
|
||||
}
|
||||
}
|
||||
|
||||
return VideoWorker_inner;
|
||||
}());
|
||||
|
||||
VideoWorker.prototype.parseURL = function (url) {
|
||||
// parse youtube ID
|
||||
function getYoutubeID (ytUrl) {
|
||||
var regExp = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/;
|
||||
var match = ytUrl.match(regExp);
|
||||
return match && match[1].length === 11 ? match[1] : false;
|
||||
}
|
||||
|
||||
// parse vimeo ID
|
||||
function getVimeoID (vmUrl) {
|
||||
var regExp = /https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)/;
|
||||
var match = vmUrl.match(regExp);
|
||||
return match && match[3] ? match[3] : false;
|
||||
}
|
||||
|
||||
// parse local string
|
||||
function getLocalVideos (locUrl) {
|
||||
var videoFormats = locUrl.split(/,(?=mp4\:|webm\:|ogv\:|ogg\:)/);
|
||||
var result = {};
|
||||
var ready = 0;
|
||||
for(var k = 0; k < videoFormats.length; k++) {
|
||||
var match = videoFormats[k].match(/^(mp4|webm|ogv|ogg)\:(.*)/);
|
||||
if(match && match[1] && match[2]) {
|
||||
result[match[1] === 'ogv' ? 'ogg' : match[1]] = match[2];
|
||||
ready = 1;
|
||||
}
|
||||
}
|
||||
return ready ? result : false;
|
||||
}
|
||||
|
||||
var Youtube = getYoutubeID(url);
|
||||
var Vimeo = getVimeoID(url);
|
||||
var Local = getLocalVideos(url);
|
||||
|
||||
if(Youtube) {
|
||||
this.type = 'youtube';
|
||||
return Youtube;
|
||||
} else if (Vimeo) {
|
||||
this.type = 'vimeo';
|
||||
return Vimeo;
|
||||
} else if (Local) {
|
||||
this.type = 'local';
|
||||
return Local;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
VideoWorker.prototype.isValid = function () {
|
||||
return !!this.videoID;
|
||||
};
|
||||
|
||||
// events
|
||||
VideoWorker.prototype.on = function (name, callback) {
|
||||
this.userEventsList = this.userEventsList || [];
|
||||
|
||||
// add new callback in events list
|
||||
(this.userEventsList[name] || (this.userEventsList[name] = [])).push(callback);
|
||||
};
|
||||
VideoWorker.prototype.off = function (name, callback) {
|
||||
if(!this.userEventsList || !this.userEventsList[name]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!callback) {
|
||||
delete this.userEventsList[name];
|
||||
} else {
|
||||
for(var k = 0; k < this.userEventsList[name].length; k++) {
|
||||
if(this.userEventsList[name][k] === callback) {
|
||||
this.userEventsList[name][k] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
VideoWorker.prototype.fire = function (name) {
|
||||
var args = [].slice.call(arguments, 1);
|
||||
if(this.userEventsList && typeof this.userEventsList[name] !== 'undefined') {
|
||||
for(var k in this.userEventsList[name]) {
|
||||
// call with all arguments
|
||||
if(this.userEventsList[name][k]) {
|
||||
this.userEventsList[name][k].apply(this, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VideoWorker.prototype.play = function (start) {
|
||||
var _this = this;
|
||||
if(!_this.player) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(_this.type === 'youtube' && _this.player.playVideo) {
|
||||
if(typeof start !== 'undefined') {
|
||||
_this.player.seekTo(start || 0);
|
||||
}
|
||||
_this.player.playVideo();
|
||||
}
|
||||
|
||||
if(_this.type === 'vimeo') {
|
||||
if (typeof start !== 'undefined') {
|
||||
_this.player.setCurrentTime(start);
|
||||
}
|
||||
_this.player.getPaused().then(function(paused) {
|
||||
if (paused) {
|
||||
_this.player.play();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(_this.type === 'local') {
|
||||
if(typeof start !== 'undefined') {
|
||||
_this.player.currentTime = start;
|
||||
}
|
||||
_this.player.play();
|
||||
}
|
||||
};
|
||||
|
||||
VideoWorker.prototype.pause = function () {
|
||||
if(!this.player) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.type === 'youtube' && this.player.pauseVideo) {
|
||||
this.player.pauseVideo();
|
||||
}
|
||||
|
||||
if(this.type === 'vimeo') {
|
||||
this.player.pause();
|
||||
}
|
||||
|
||||
if(this.type === 'local') {
|
||||
this.player.pause();
|
||||
}
|
||||
};
|
||||
|
||||
VideoWorker.prototype.getImageURL = function (callback) {
|
||||
var _this = this;
|
||||
|
||||
if(_this.videoImage) {
|
||||
callback(_this.videoImage);
|
||||
return;
|
||||
}
|
||||
|
||||
if(_this.type === 'youtube') {
|
||||
var availableSizes = [
|
||||
'maxresdefault',
|
||||
'sddefault',
|
||||
'hqdefault',
|
||||
'0'
|
||||
];
|
||||
var step = 0;
|
||||
|
||||
var tempImg = new Image();
|
||||
tempImg.onload = function () {
|
||||
// if no thumbnail, youtube add their own image with width = 120px
|
||||
if ((this.naturalWidth || this.width) !== 120 || step === availableSizes.length - 1) {
|
||||
// ok
|
||||
_this.videoImage = 'https://img.youtube.com/vi/' + _this.videoID + '/' + availableSizes[step] + '.jpg';
|
||||
callback(_this.videoImage);
|
||||
} else {
|
||||
// try another size
|
||||
step++;
|
||||
this.src = 'https://img.youtube.com/vi/' + _this.videoID + '/' + availableSizes[step] + '.jpg';
|
||||
}
|
||||
};
|
||||
tempImg.src = 'https://img.youtube.com/vi/' + _this.videoID + '/' + availableSizes[step] + '.jpg';
|
||||
}
|
||||
|
||||
if(_this.type === 'vimeo') {
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', 'https://vimeo.com/api/v2/video/' + _this.videoID + '.json', true);
|
||||
request.onreadystatechange = function () {
|
||||
if (this.readyState === 4) {
|
||||
if (this.status >= 200 && this.status < 400) {
|
||||
// Success!
|
||||
var response = JSON.parse(this.responseText);
|
||||
_this.videoImage = response[0].thumbnail_large;
|
||||
callback(_this.videoImage);
|
||||
} else {
|
||||
// Error :(
|
||||
}
|
||||
}
|
||||
};
|
||||
request.send();
|
||||
request = null;
|
||||
}
|
||||
};
|
||||
|
||||
VideoWorker.prototype.getIframe = function (callback) {
|
||||
var _this = this;
|
||||
|
||||
// return generated iframe
|
||||
if(_this.$iframe) {
|
||||
callback(_this.$iframe);
|
||||
return;
|
||||
}
|
||||
|
||||
// generate new iframe
|
||||
_this.onAPIready(function () {
|
||||
var hiddenDiv;
|
||||
if(!_this.$iframe) {
|
||||
hiddenDiv = document.createElement('div');
|
||||
hiddenDiv.style.display = 'none';
|
||||
}
|
||||
|
||||
// Youtube
|
||||
if(_this.type === 'youtube') {
|
||||
_this.playerOptions = {};
|
||||
_this.playerOptions.videoId = _this.videoID;
|
||||
_this.playerOptions.playerVars = {
|
||||
autohide: 1,
|
||||
rel: 0,
|
||||
autoplay: 0
|
||||
};
|
||||
|
||||
// hide controls
|
||||
if(!_this.options.controls) {
|
||||
_this.playerOptions.playerVars.iv_load_policy = 3;
|
||||
_this.playerOptions.playerVars.modestbranding = 1;
|
||||
_this.playerOptions.playerVars.controls = 0;
|
||||
_this.playerOptions.playerVars.showinfo = 0;
|
||||
_this.playerOptions.playerVars.disablekb = 1;
|
||||
}
|
||||
|
||||
// events
|
||||
var ytStarted;
|
||||
var ytProgressInterval;
|
||||
_this.playerOptions.events = {
|
||||
onReady: function (e) {
|
||||
// mute
|
||||
if(_this.options.mute) {
|
||||
e.target.mute();
|
||||
}
|
||||
// autoplay
|
||||
if(_this.options.autoplay) {
|
||||
_this.play(_this.options.startTime);
|
||||
}
|
||||
_this.fire('ready', e);
|
||||
},
|
||||
onStateChange: function (e) {
|
||||
// loop
|
||||
if(_this.options.loop && e.data === YT.PlayerState.ENDED) {
|
||||
_this.play(_this.options.startTime);
|
||||
}
|
||||
if(!ytStarted && e.data === YT.PlayerState.PLAYING) {
|
||||
ytStarted = 1;
|
||||
_this.fire('started', e);
|
||||
}
|
||||
if(e.data === YT.PlayerState.PLAYING) {
|
||||
_this.fire('play', e);
|
||||
}
|
||||
if(e.data === YT.PlayerState.PAUSED) {
|
||||
_this.fire('pause', e);
|
||||
}
|
||||
if(e.data === YT.PlayerState.ENDED) {
|
||||
_this.fire('end', e);
|
||||
}
|
||||
|
||||
// check for end of video and play again or stop
|
||||
if(_this.options.endTime) {
|
||||
if(e.data === YT.PlayerState.PLAYING) {
|
||||
ytProgressInterval = setInterval(function () {
|
||||
if(_this.options.endTime && _this.player.getCurrentTime() >= _this.options.endTime) {
|
||||
if(_this.options.loop) {
|
||||
_this.play(_this.options.startTime);
|
||||
} else {
|
||||
_this.pause();
|
||||
}
|
||||
}
|
||||
}, 150);
|
||||
} else {
|
||||
clearInterval(ytProgressInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var firstInit = !_this.$iframe;
|
||||
if(firstInit) {
|
||||
var div = document.createElement('div');
|
||||
div.setAttribute('id', _this.playerID);
|
||||
hiddenDiv.appendChild(div);
|
||||
document.body.appendChild(hiddenDiv);
|
||||
}
|
||||
_this.player = _this.player || new window.YT.Player(_this.playerID, _this.playerOptions);
|
||||
if(firstInit) {
|
||||
_this.$iframe = document.getElementById(_this.playerID);
|
||||
|
||||
// get video width and height
|
||||
_this.videoWidth = parseInt(_this.$iframe.getAttribute('width'), 10) || 1280;
|
||||
_this.videoHeight = parseInt(_this.$iframe.getAttribute('height'), 10) || 720;
|
||||
}
|
||||
}
|
||||
|
||||
// Vimeo
|
||||
if(_this.type === 'vimeo') {
|
||||
_this.playerOptions = '';
|
||||
|
||||
_this.playerOptions += 'player_id=' + _this.playerID;
|
||||
_this.playerOptions += '&autopause=0';
|
||||
|
||||
// hide controls
|
||||
if(!_this.options.controls) {
|
||||
_this.playerOptions += '&badge=0&byline=0&portrait=0&title=0';
|
||||
}
|
||||
|
||||
// autoplay
|
||||
_this.playerOptions += '&autoplay=' + (_this.options.autoplay ? '1' : '0');
|
||||
|
||||
// loop
|
||||
_this.playerOptions += '&loop=' + (_this.options.loop ? 1 : 0);
|
||||
|
||||
if(!_this.$iframe) {
|
||||
_this.$iframe = document.createElement('iframe');
|
||||
_this.$iframe.setAttribute('id', _this.playerID);
|
||||
_this.$iframe.setAttribute('src', 'https://player.vimeo.com/video/' + _this.videoID + '?' + _this.playerOptions);
|
||||
_this.$iframe.setAttribute('frameborder', '0');
|
||||
hiddenDiv.appendChild(_this.$iframe);
|
||||
document.body.appendChild(hiddenDiv);
|
||||
}
|
||||
|
||||
_this.player = _this.player || new Vimeo.Player(_this.$iframe);
|
||||
|
||||
// get video width and height
|
||||
_this.player.getVideoWidth().then(function (width) {
|
||||
_this.videoWidth = width || 1280;
|
||||
});
|
||||
_this.player.getVideoHeight().then(function (height) {
|
||||
_this.videoHeight = height || 720;
|
||||
});
|
||||
|
||||
// mute
|
||||
_this.player.setVolume(_this.options.mute ? 0 : 100);
|
||||
|
||||
var vmStarted;
|
||||
_this.player.on('timeupdate', function (e) {
|
||||
if(!vmStarted) {
|
||||
_this.fire('started', e);
|
||||
}
|
||||
vmStarted = 1;
|
||||
|
||||
// check for end of video and play again or stop
|
||||
if(_this.options.endTime) {
|
||||
if(_this.options.endTime && e.seconds >= _this.options.endTime) {
|
||||
if(_this.options.loop) {
|
||||
_this.play(_this.options.startTime);
|
||||
} else {
|
||||
_this.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
_this.player.on('play', function (e) {
|
||||
_this.fire('play', e);
|
||||
|
||||
// check for the start time and start with it
|
||||
if(_this.options.startTime && e.seconds === 0) {
|
||||
_this.play(_this.options.startTime);
|
||||
}
|
||||
});
|
||||
_this.player.on('pause', function (e) {
|
||||
_this.fire('pause', e);
|
||||
});
|
||||
_this.player.on('ended', function (e) {
|
||||
_this.fire('end', e);
|
||||
});
|
||||
_this.player.on('loaded', function (e) {
|
||||
_this.fire('ready', e);
|
||||
});
|
||||
}
|
||||
|
||||
// Local
|
||||
function addSourceToLocal (element, src, type) {
|
||||
var source = document.createElement('source');
|
||||
source.src = src;
|
||||
source.type = type;
|
||||
element.appendChild(source);
|
||||
}
|
||||
if(_this.type === 'local') {
|
||||
if(!_this.$iframe) {
|
||||
_this.$iframe = document.createElement('video');
|
||||
|
||||
// mute
|
||||
if(_this.options.mute) {
|
||||
_this.$iframe.muted = true;
|
||||
}
|
||||
|
||||
// loop
|
||||
if(_this.options.loop) {
|
||||
_this.$iframe.loop = true;
|
||||
}
|
||||
|
||||
_this.$iframe.setAttribute('id', _this.playerID);
|
||||
hiddenDiv.appendChild(_this.$iframe);
|
||||
document.body.appendChild(hiddenDiv);
|
||||
|
||||
for(var k in _this.videoID) {
|
||||
addSourceToLocal(_this.$iframe, _this.videoID[k], 'video/' + k);
|
||||
}
|
||||
}
|
||||
|
||||
_this.player = _this.player || _this.$iframe;
|
||||
|
||||
var locStarted;
|
||||
addEventListener(_this.player, 'playing', function (e) {
|
||||
if(!locStarted) {
|
||||
_this.fire('started', e);
|
||||
}
|
||||
locStarted = 1;
|
||||
});
|
||||
addEventListener(_this.player, 'timeupdate', function () {
|
||||
// check for end of video and play again or stop
|
||||
if(_this.options.endTime) {
|
||||
if(_this.options.endTime && this.currentTime >= _this.options.endTime) {
|
||||
if(_this.options.loop) {
|
||||
_this.play(_this.options.startTime);
|
||||
} else {
|
||||
_this.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
addEventListener(_this.player, 'play', function (e) {
|
||||
_this.fire('play', e);
|
||||
});
|
||||
addEventListener(_this.player, 'pause', function (e) {
|
||||
_this.fire('pause', e);
|
||||
});
|
||||
addEventListener(_this.player, 'ended', function (e) {
|
||||
_this.fire('end', e);
|
||||
});
|
||||
addEventListener(_this.player, 'loadedmetadata', function () {
|
||||
// get video width and height
|
||||
_this.videoWidth = this.videoWidth || 1280;
|
||||
_this.videoHeight = this.videoHeight || 720;
|
||||
|
||||
_this.fire('ready');
|
||||
|
||||
// autoplay
|
||||
if(_this.options.autoplay) {
|
||||
_this.play(_this.options.startTime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
callback(_this.$iframe);
|
||||
});
|
||||
};
|
||||
|
||||
VideoWorker.prototype.init = function () {
|
||||
var _this = this;
|
||||
|
||||
_this.playerID = 'VideoWorker-' + _this.ID;
|
||||
};
|
||||
|
||||
var YoutubeAPIadded = 0;
|
||||
var VimeoAPIadded = 0;
|
||||
VideoWorker.prototype.loadAPI = function () {
|
||||
var _this = this;
|
||||
|
||||
if(YoutubeAPIadded && VimeoAPIadded) {
|
||||
return;
|
||||
}
|
||||
|
||||
var src = '';
|
||||
|
||||
// load Youtube API
|
||||
if(_this.type === 'youtube' && !YoutubeAPIadded) {
|
||||
YoutubeAPIadded = 1;
|
||||
src = '//www.youtube.com/iframe_api';
|
||||
}
|
||||
|
||||
// load Vimeo API
|
||||
if(_this.type === 'vimeo' && !VimeoAPIadded) {
|
||||
VimeoAPIadded = 1;
|
||||
src = '//player.vimeo.com/api/player.js';
|
||||
}
|
||||
|
||||
if(!src) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (window.location.origin === 'file://') {
|
||||
src = 'http:' + src;
|
||||
}
|
||||
|
||||
// add script in head section
|
||||
var tag = document.createElement('script');
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
tag.src = src;
|
||||
|
||||
head.appendChild(tag);
|
||||
|
||||
head = null;
|
||||
tag = null;
|
||||
};
|
||||
|
||||
var loadingYoutubePlayer = 0;
|
||||
var loadingVimeoPlayer = 0;
|
||||
var loadingYoutubeDeffer = new Deferred();
|
||||
var loadingVimeoDeffer = new Deferred();
|
||||
VideoWorker.prototype.onAPIready = function (callback) {
|
||||
var _this = this;
|
||||
|
||||
// Youtube
|
||||
if(_this.type === 'youtube') {
|
||||
// Listen for global YT player callback
|
||||
if ((typeof YT === 'undefined' || YT.loaded === 0) && !loadingYoutubePlayer) {
|
||||
// Prevents Ready event from being called twice
|
||||
loadingYoutubePlayer = 1;
|
||||
|
||||
// Creates deferred so, other players know when to wait.
|
||||
window.onYouTubeIframeAPIReady = function () {
|
||||
window.onYouTubeIframeAPIReady = null;
|
||||
loadingYoutubeDeffer.resolve('done');
|
||||
callback();
|
||||
};
|
||||
} else if (typeof YT === 'object' && YT.loaded === 1) {
|
||||
callback();
|
||||
} else {
|
||||
loadingYoutubeDeffer.done(function () {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Vimeo
|
||||
if(_this.type === 'vimeo') {
|
||||
if(typeof Vimeo === 'undefined' && !loadingVimeoPlayer) {
|
||||
loadingVimeoPlayer = 1;
|
||||
var vimeo_interval = setInterval(function () {
|
||||
if(typeof Vimeo !== 'undefined') {
|
||||
clearInterval(vimeo_interval);
|
||||
loadingVimeoDeffer.resolve('done');
|
||||
callback();
|
||||
}
|
||||
}, 20);
|
||||
} else if (typeof Vimeo !== 'undefined') {
|
||||
callback();
|
||||
} else {
|
||||
loadingVimeoDeffer.done(function () {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Local
|
||||
if(_this.type === 'local') {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
window.VideoWorker = VideoWorker;
|
||||
}(window));
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* Name : Video Background Extension for Jarallax
|
||||
* Version : 1.0.0
|
||||
* Author : _nK http://nkdev.info
|
||||
* GitHub : https://github.com/nk-o/jarallax
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if(typeof jarallax === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
var Jarallax = jarallax.constructor;
|
||||
|
||||
// append video after init Jarallax
|
||||
var def_init = Jarallax.prototype.init;
|
||||
Jarallax.prototype.init = function () {
|
||||
var _this = this;
|
||||
|
||||
def_init.apply(_this);
|
||||
|
||||
if(_this.video) {
|
||||
_this.video.getIframe(function (iframe) {
|
||||
var $parent = iframe.parentNode;
|
||||
_this.css(iframe, {
|
||||
position: _this.image.position,
|
||||
top: '0px', left: '0px', right: '0px', bottom: '0px',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
maxWidth: 'none',
|
||||
maxHeight: 'none',
|
||||
visibility: 'hidden',
|
||||
margin: 0,
|
||||
zIndex: -1
|
||||
});
|
||||
_this.$video = iframe;
|
||||
_this.image.$container.appendChild(iframe);
|
||||
|
||||
// remove parent iframe element (created by VideoWorker)
|
||||
$parent.parentNode.removeChild($parent);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// cover video
|
||||
var def_coverImage = Jarallax.prototype.coverImage;
|
||||
Jarallax.prototype.coverImage = function () {
|
||||
var _this = this;
|
||||
|
||||
def_coverImage.apply(_this);
|
||||
|
||||
// add video height over than need to hide controls
|
||||
if(_this.video && _this.image.$item.nodeName === 'IFRAME') {
|
||||
_this.css(_this.image.$item, {
|
||||
height: _this.image.$item.getBoundingClientRect().height + 400 + 'px',
|
||||
marginTop: (-200 + parseFloat(_this.css(_this.image.$item, 'margin-top'))) + 'px'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// init video
|
||||
var def_initImg = Jarallax.prototype.initImg;
|
||||
Jarallax.prototype.initImg = function () {
|
||||
var _this = this;
|
||||
var defaultResult = def_initImg.apply(_this);
|
||||
|
||||
if(!_this.options.videoSrc) {
|
||||
_this.options.videoSrc = _this.$item.getAttribute('data-jarallax-video') || false;
|
||||
}
|
||||
|
||||
if(_this.options.videoSrc) {
|
||||
var video = new VideoWorker(_this.options.videoSrc, {
|
||||
startTime: _this.options.videoStartTime || 0,
|
||||
endTime: _this.options.videoEndTime || 0
|
||||
});
|
||||
|
||||
if(video.isValid()) {
|
||||
_this.image.useImgTag = true;
|
||||
|
||||
video.on('ready', function () {
|
||||
var oldOnScroll = _this.onScroll;
|
||||
_this.onScroll = function () {
|
||||
oldOnScroll.apply(_this);
|
||||
if(_this.isVisible()) {
|
||||
video.play();
|
||||
} else {
|
||||
video.pause();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
video.on('started', function () {
|
||||
_this.image.$default_item = _this.image.$item;
|
||||
_this.image.$item = _this.$video;
|
||||
|
||||
// set video width and height
|
||||
_this.image.width = _this.options.imgWidth = _this.video.videoWidth || 1280;
|
||||
_this.image.height = _this.options.imgHeight = _this.video.videoHeight || 720;
|
||||
_this.coverImage();
|
||||
_this.clipContainer();
|
||||
_this.onScroll();
|
||||
|
||||
// hide image
|
||||
if(_this.image.$default_item) {
|
||||
_this.image.$default_item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
_this.video = video;
|
||||
|
||||
if(video.type !== 'local') {
|
||||
video.getImageURL(function (url) {
|
||||
_this.image.src = url;
|
||||
_this.init();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// prevent default image loading when not local video
|
||||
if(video.type !== 'local') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// set empty image on local video if not defined
|
||||
else if (!defaultResult) {
|
||||
_this.image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultResult;
|
||||
};
|
||||
|
||||
// Destroy video parallax
|
||||
var def_destroy = Jarallax.prototype.destroy;
|
||||
Jarallax.prototype.destroy = function () {
|
||||
var _this = this;
|
||||
|
||||
def_destroy.apply(_this);
|
||||
};
|
||||
}());
|
||||
Executable
+695
@@ -0,0 +1,695 @@
|
||||
/*!
|
||||
* Name : Just Another Parallax [Jarallax]
|
||||
* Version : 1.8.0
|
||||
* Author : _nK https://nkdev.info
|
||||
* GitHub : https://github.com/nk-o/jarallax
|
||||
*/
|
||||
(function (window) {
|
||||
'use strict';
|
||||
|
||||
// Adapted from https://gist.github.com/paulirish/1579671
|
||||
if(!Date.now) {
|
||||
Date.now = function () { return new Date().getTime(); };
|
||||
}
|
||||
if(!window.requestAnimationFrame) {
|
||||
(function () {
|
||||
|
||||
var vendors = ['webkit', 'moz'];
|
||||
for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
|
||||
var vp = vendors[i];
|
||||
window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
|
||||
window.cancelAnimationFrame = window[vp+'CancelAnimationFrame']
|
||||
|| window[vp+'CancelRequestAnimationFrame'];
|
||||
}
|
||||
if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
|
||||
|| !window.requestAnimationFrame || !window.cancelAnimationFrame) {
|
||||
var lastTime = 0;
|
||||
window.requestAnimationFrame = function (callback) {
|
||||
var now = Date.now();
|
||||
var nextTime = Math.max(lastTime + 16, now);
|
||||
return setTimeout(function () { callback(lastTime = nextTime); },
|
||||
nextTime - now);
|
||||
};
|
||||
window.cancelAnimationFrame = clearTimeout;
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
// test if css property supported by browser
|
||||
// like "transform"
|
||||
var tempDiv = document.createElement('div');
|
||||
function isPropertySupported (property) {
|
||||
var prefixes = ['O','Moz','ms','Ms','Webkit'];
|
||||
var i = prefixes.length;
|
||||
if (tempDiv.style[property] !== undefined) {
|
||||
return true;
|
||||
}
|
||||
property = property.charAt(0).toUpperCase() + property.substr(1);
|
||||
while (--i > -1 && tempDiv.style[prefixes[i] + property] === undefined) { }
|
||||
return i >= 0;
|
||||
}
|
||||
|
||||
var supportTransform = isPropertySupported('transform');
|
||||
var supportTransform3D = isPropertySupported('perspective');
|
||||
|
||||
var ua = navigator.userAgent;
|
||||
var isAndroid = ua.toLowerCase().indexOf('android') > -1;
|
||||
var isIOs = /iPad|iPhone|iPod/.test(ua) && !window.MSStream;
|
||||
var isFirefox = ua.toLowerCase().indexOf('firefox') > -1;
|
||||
var isIE = ua.indexOf('MSIE ') > -1 // IE 10 or older
|
||||
|| ua.indexOf('Trident/') > -1 // IE 11
|
||||
|| ua.indexOf('Edge/') > -1; // Edge
|
||||
var isIElt10 = document.all && !window.atob; // IE 9 or older
|
||||
|
||||
var wndW;
|
||||
var wndH;
|
||||
function updateWndVars () {
|
||||
wndW = window.innerWidth || document.documentElement.clientWidth;
|
||||
wndH = window.innerHeight || document.documentElement.clientHeight;
|
||||
}
|
||||
updateWndVars();
|
||||
|
||||
// list with all jarallax instances
|
||||
// need to render all in one scroll/resize event
|
||||
var jarallaxList = [];
|
||||
|
||||
// Jarallax instance
|
||||
var Jarallax = (function () {
|
||||
var instanceID = 0;
|
||||
|
||||
function Jarallax_inner (item, userOptions) {
|
||||
var _this = this,
|
||||
dataOptions;
|
||||
|
||||
_this.$item = item;
|
||||
|
||||
_this.defaults = {
|
||||
type : 'scroll', // type of parallax: scroll, scale, opacity, scale-opacity, scroll-opacity
|
||||
speed : 0.5, // supported value from -1 to 2
|
||||
imgSrc : null,
|
||||
imgWidth : null,
|
||||
imgHeight : null,
|
||||
elementInViewport : null,
|
||||
zIndex : -100,
|
||||
noAndroid : false,
|
||||
noIos : true,
|
||||
|
||||
// events
|
||||
onScroll : null, // function(calculations) {}
|
||||
onInit : null, // function() {}
|
||||
onDestroy : null, // function() {}
|
||||
onCoverImage : null // function() {}
|
||||
};
|
||||
dataOptions = JSON.parse(_this.$item.getAttribute('data-jarallax') || '{}');
|
||||
_this.options = _this.extend({}, _this.defaults, dataOptions, userOptions);
|
||||
|
||||
// stop init if android or ios
|
||||
if(!supportTransform || isAndroid && _this.options.noAndroid || isIOs && _this.options.noIos) {
|
||||
return;
|
||||
}
|
||||
|
||||
// fix speed option [-1.0, 2.0]
|
||||
_this.options.speed = Math.min(2, Math.max(-1, parseFloat(_this.options.speed)));
|
||||
|
||||
// custom element to check if parallax in viewport
|
||||
var elementInVP = _this.options.elementInViewport;
|
||||
// get first item from array
|
||||
if(elementInVP && typeof elementInVP === 'object' && typeof elementInVP.length !== 'undefined') {
|
||||
elementInVP = elementInVP[0];
|
||||
}
|
||||
// check if dom element
|
||||
if(!elementInVP instanceof Element) {
|
||||
elementInVP = null;
|
||||
}
|
||||
_this.options.elementInViewport = elementInVP;
|
||||
|
||||
_this.instanceID = instanceID++;
|
||||
|
||||
_this.image = {
|
||||
src : _this.options.imgSrc || null,
|
||||
$container : null,
|
||||
$item : null,
|
||||
width : _this.options.imgWidth || null,
|
||||
height : _this.options.imgHeight || null,
|
||||
// fix for some devices
|
||||
// use <img> instead of background image - more smoothly
|
||||
useImgTag : isIOs || isAndroid || isIE,
|
||||
|
||||
// position absolute is needed on IE9 and FireFox because fixed position have glitches
|
||||
position : !supportTransform3D || isFirefox ? 'absolute' : 'fixed'
|
||||
};
|
||||
|
||||
if(_this.initImg()) {
|
||||
_this.init();
|
||||
}
|
||||
}
|
||||
|
||||
return Jarallax_inner;
|
||||
}());
|
||||
|
||||
// add styles to element
|
||||
Jarallax.prototype.css = function (el, styles) {
|
||||
if(typeof styles === 'string') {
|
||||
if(window.getComputedStyle) {
|
||||
return window.getComputedStyle(el).getPropertyValue(styles);
|
||||
}
|
||||
return el.style[styles];
|
||||
}
|
||||
|
||||
// add transform property with vendor prefixes
|
||||
if(styles.transform) {
|
||||
if (supportTransform3D) {
|
||||
styles.transform += ' translateZ(0)';
|
||||
}
|
||||
styles.WebkitTransform = styles.MozTransform = styles.msTransform = styles.OTransform = styles.transform;
|
||||
}
|
||||
|
||||
for(var k in styles) {
|
||||
el.style[k] = styles[k];
|
||||
}
|
||||
return el;
|
||||
};
|
||||
// Extend like jQuery.extend
|
||||
Jarallax.prototype.extend = function (out) {
|
||||
out = out || {};
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
if (!arguments[i]) {
|
||||
continue;
|
||||
}
|
||||
for (var key in arguments[i]) {
|
||||
if (arguments[i].hasOwnProperty(key)) {
|
||||
out[key] = arguments[i][key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
// Jarallax functions
|
||||
Jarallax.prototype.initImg = function () {
|
||||
var _this = this;
|
||||
|
||||
// get image src
|
||||
if(_this.image.src === null) {
|
||||
_this.image.src = _this.css(_this.$item, 'background-image').replace(/^url\(['"]?/g,'').replace(/['"]?\)$/g,'');
|
||||
}
|
||||
return !(!_this.image.src || _this.image.src === 'none');
|
||||
};
|
||||
|
||||
Jarallax.prototype.init = function () {
|
||||
var _this = this,
|
||||
containerStyles = {
|
||||
position : 'absolute',
|
||||
top : 0,
|
||||
left : 0,
|
||||
width : '100%',
|
||||
height : '100%',
|
||||
overflow : 'hidden',
|
||||
pointerEvents : 'none'
|
||||
},
|
||||
imageStyles = {};
|
||||
|
||||
// save default user styles
|
||||
_this.$item.setAttribute('data-jarallax-original-styles', _this.$item.getAttribute('style'));
|
||||
|
||||
// set relative position and z-index to the parent
|
||||
if (_this.css(_this.$item, 'position') === 'static') {
|
||||
_this.css(_this.$item, {
|
||||
position: 'relative'
|
||||
});
|
||||
}
|
||||
if (_this.css(_this.$item, 'z-index') === 'auto') {
|
||||
_this.css(_this.$item, {
|
||||
zIndex: 0
|
||||
});
|
||||
}
|
||||
|
||||
// container for parallax image
|
||||
_this.image.$container = document.createElement('div');
|
||||
_this.css(_this.image.$container, containerStyles);
|
||||
_this.css(_this.image.$container, {
|
||||
visibility : 'hidden',
|
||||
'z-index' : _this.options.zIndex
|
||||
});
|
||||
_this.image.$container.setAttribute('id', 'jarallax-container-' + _this.instanceID);
|
||||
_this.$item.appendChild(_this.image.$container);
|
||||
|
||||
// use img tag
|
||||
if(_this.image.useImgTag) {
|
||||
_this.image.$item = document.createElement('img');
|
||||
_this.image.$item.setAttribute('src', _this.image.src);
|
||||
imageStyles = _this.extend({
|
||||
'max-width' : 'none'
|
||||
}, containerStyles, imageStyles);
|
||||
}
|
||||
|
||||
// use div with background image
|
||||
else {
|
||||
_this.image.$item = document.createElement('div');
|
||||
imageStyles = _this.extend({
|
||||
'background-position' : '50% 50%',
|
||||
'background-size' : '100% auto',
|
||||
'background-repeat' : 'no-repeat no-repeat',
|
||||
'background-image' : 'url("' + _this.image.src + '")'
|
||||
}, containerStyles, imageStyles);
|
||||
}
|
||||
|
||||
// check if one of parents have transform style (without this check, scroll transform will be inverted)
|
||||
// discussion - https://github.com/nk-o/jarallax/issues/9
|
||||
var parentWithTransform = 0;
|
||||
var $itemParents = _this.$item;
|
||||
while ($itemParents !== null && $itemParents !== document && parentWithTransform === 0) {
|
||||
var parent_transform = _this.css($itemParents, '-webkit-transform') || _this.css($itemParents, '-moz-transform') || _this.css($itemParents, 'transform');
|
||||
if(parent_transform && parent_transform !== 'none') {
|
||||
parentWithTransform = 1;
|
||||
|
||||
// add transform on parallax container if there is parent with transform
|
||||
_this.css(_this.image.$container, {
|
||||
transform: 'translateX(0) translateY(0)'
|
||||
});
|
||||
}
|
||||
$itemParents = $itemParents.parentNode;
|
||||
}
|
||||
|
||||
// absolute position if one of parents have transformations or parallax without scroll
|
||||
if (parentWithTransform || _this.options.type === 'opacity'|| _this.options.type === 'scale' || _this.options.type === 'scale-opacity') {
|
||||
_this.image.position = 'absolute';
|
||||
}
|
||||
|
||||
// add position to parallax block
|
||||
imageStyles.position = _this.image.position;
|
||||
|
||||
// parallax image
|
||||
_this.css(_this.image.$item, imageStyles);
|
||||
_this.image.$container.appendChild(_this.image.$item);
|
||||
|
||||
// cover image if width and height is ready
|
||||
function initAfterReady () {
|
||||
_this.coverImage();
|
||||
_this.clipContainer();
|
||||
_this.onScroll(true);
|
||||
|
||||
// call onInit event
|
||||
if(_this.options.onInit) {
|
||||
_this.options.onInit.call(_this);
|
||||
}
|
||||
|
||||
// timeout to fix IE blinking
|
||||
setTimeout(function () {
|
||||
if(_this.$item) {
|
||||
// remove default user background
|
||||
_this.css(_this.$item, {
|
||||
'background-image' : 'none',
|
||||
'background-attachment' : 'scroll',
|
||||
'background-size' : 'auto'
|
||||
});
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
if(_this.image.width && _this.image.height) {
|
||||
// init if width and height already exists
|
||||
initAfterReady();
|
||||
} else {
|
||||
// load image and get width and height
|
||||
_this.getImageSize(_this.image.src, function (width, height) {
|
||||
_this.image.width = width;
|
||||
_this.image.height = height;
|
||||
initAfterReady();
|
||||
});
|
||||
}
|
||||
|
||||
jarallaxList.push(_this);
|
||||
};
|
||||
|
||||
Jarallax.prototype.destroy = function () {
|
||||
var _this = this;
|
||||
|
||||
// remove from instances list
|
||||
for(var k = 0, len = jarallaxList.length; k < len; k++) {
|
||||
if(jarallaxList[k].instanceID === _this.instanceID) {
|
||||
jarallaxList.splice(k, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// return styles on container as before jarallax init
|
||||
var originalStylesTag = _this.$item.getAttribute('data-jarallax-original-styles');
|
||||
_this.$item.removeAttribute('data-jarallax-original-styles');
|
||||
// null occurs if there is no style tag before jarallax init
|
||||
if(originalStylesTag === 'null') {
|
||||
_this.$item.removeAttribute('style');
|
||||
} else {
|
||||
_this.$item.setAttribute('style', originalStylesTag);
|
||||
}
|
||||
|
||||
// remove additional dom elements
|
||||
if(_this.$clipStyles) {
|
||||
_this.$clipStyles.parentNode.removeChild(_this.$clipStyles);
|
||||
}
|
||||
_this.image.$container.parentNode.removeChild(_this.image.$container);
|
||||
|
||||
// call onDestroy event
|
||||
if(_this.options.onDestroy) {
|
||||
_this.options.onDestroy.call(_this);
|
||||
}
|
||||
|
||||
// delete jarallax from item
|
||||
delete _this.$item.jarallax;
|
||||
|
||||
// delete all variables
|
||||
for(var n in _this) {
|
||||
delete _this[n];
|
||||
}
|
||||
};
|
||||
|
||||
Jarallax.prototype.getImageSize = function (src, callback) {
|
||||
if(!src || !callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tempImg = new Image();
|
||||
tempImg.onload = function () {
|
||||
callback(tempImg.width, tempImg.height);
|
||||
};
|
||||
tempImg.src = src;
|
||||
};
|
||||
|
||||
// it will remove some image overlapping
|
||||
// overlapping occur due to an image position fixed inside absolute position element (webkit based browsers works without any fix)
|
||||
Jarallax.prototype.clipContainer = function () {
|
||||
// clip is not working properly on real IE9 and less
|
||||
if(isIElt10) {
|
||||
return;
|
||||
}
|
||||
|
||||
var _this = this,
|
||||
rect = _this.image.$container.getBoundingClientRect(),
|
||||
width = rect.width,
|
||||
height = rect.height;
|
||||
|
||||
if(!_this.$clipStyles) {
|
||||
_this.$clipStyles = document.createElement('style');
|
||||
_this.$clipStyles.setAttribute('type', 'text/css');
|
||||
_this.$clipStyles.setAttribute('id', '#jarallax-clip-' + _this.instanceID);
|
||||
var head = document.head || document.getElementsByTagName('head')[0];
|
||||
head.appendChild(_this.$clipStyles);
|
||||
}
|
||||
|
||||
var styles = [
|
||||
'#jarallax-container-' + _this.instanceID + ' {',
|
||||
' clip: rect(0 ' + width + 'px ' + height + 'px 0);',
|
||||
' clip: rect(0, ' + width + 'px, ' + height + 'px, 0);',
|
||||
'}'
|
||||
].join('\n');
|
||||
|
||||
// add clip styles inline (this method need for support IE8 and less browsers)
|
||||
if (_this.$clipStyles.styleSheet){
|
||||
_this.$clipStyles.styleSheet.cssText = styles;
|
||||
} else {
|
||||
_this.$clipStyles.innerHTML = styles;
|
||||
}
|
||||
};
|
||||
|
||||
Jarallax.prototype.coverImage = function () {
|
||||
var _this = this;
|
||||
|
||||
if(!_this.image.width || !_this.image.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
var rect = _this.image.$container.getBoundingClientRect(),
|
||||
contW = rect.width,
|
||||
contH = rect.height,
|
||||
contL = rect.left,
|
||||
imgW = _this.image.width,
|
||||
imgH = _this.image.height,
|
||||
speed = _this.options.speed,
|
||||
isScroll = _this.options.type === 'scroll' || _this.options.type === 'scroll-opacity',
|
||||
scrollDist = 0,
|
||||
resultW = 0,
|
||||
resultH = contH,
|
||||
resultML = 0,
|
||||
resultMT = 0;
|
||||
|
||||
// scroll parallax
|
||||
if(isScroll) {
|
||||
// scroll distance and height for image
|
||||
if (speed < 0) {
|
||||
scrollDist = speed * Math.max(contH, wndH);
|
||||
} else {
|
||||
scrollDist = speed * (contH + wndH);
|
||||
}
|
||||
|
||||
// size for scroll parallax
|
||||
if (speed > 1) {
|
||||
resultH = Math.abs(scrollDist - wndH);
|
||||
} else if (speed < 0) {
|
||||
resultH = scrollDist / speed + Math.abs(scrollDist);
|
||||
} else {
|
||||
resultH += Math.abs(wndH - contH) * (1 - speed);
|
||||
}
|
||||
|
||||
scrollDist /= 2;
|
||||
}
|
||||
|
||||
// calculate width relative to height and image size
|
||||
resultW = resultH * imgW / imgH;
|
||||
if(resultW < contW) {
|
||||
resultW = contW;
|
||||
resultH = resultW * imgH / imgW;
|
||||
}
|
||||
|
||||
// center parallax image
|
||||
if(isScroll) {
|
||||
resultML = contL + (contW - resultW) / 2;
|
||||
resultMT = (wndH - resultH) / 2;
|
||||
} else {
|
||||
resultML = (contW - resultW) / 2;
|
||||
resultMT = (contH - resultH) / 2;
|
||||
}
|
||||
|
||||
// fix if parallax block in absolute position
|
||||
if(_this.image.position === 'absolute') {
|
||||
resultML -= contL;
|
||||
}
|
||||
|
||||
// store scroll distance
|
||||
_this.parallaxScrollDistance = scrollDist;
|
||||
|
||||
// apply result to item
|
||||
_this.css(_this.image.$item, {
|
||||
width: resultW + 'px',
|
||||
height: resultH + 'px',
|
||||
marginLeft: resultML + 'px',
|
||||
marginTop: resultMT + 'px'
|
||||
});
|
||||
|
||||
// call onCoverImage event
|
||||
if(_this.options.onCoverImage) {
|
||||
_this.options.onCoverImage.call(_this);
|
||||
}
|
||||
};
|
||||
|
||||
Jarallax.prototype.isVisible = function () {
|
||||
return this.isElementInViewport || false;
|
||||
};
|
||||
|
||||
Jarallax.prototype.onScroll = function (force) {
|
||||
var _this = this;
|
||||
|
||||
if(!_this.image.width || !_this.image.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
var rect = _this.$item.getBoundingClientRect(),
|
||||
contT = rect.top,
|
||||
contH = rect.height,
|
||||
styles = {
|
||||
visibility : 'visible',
|
||||
backgroundPosition : '50% 50%'
|
||||
};
|
||||
|
||||
// check if in viewport
|
||||
var viewportRect = rect;
|
||||
if(_this.options.elementInViewport) {
|
||||
viewportRect = _this.options.elementInViewport.getBoundingClientRect();
|
||||
}
|
||||
_this.isElementInViewport =
|
||||
viewportRect.bottom >= 0 &&
|
||||
viewportRect.right >= 0 &&
|
||||
viewportRect.top <= wndH &&
|
||||
viewportRect.left <= wndW;
|
||||
|
||||
// stop calculations if item is not in viewport
|
||||
if (force ? false : !_this.isElementInViewport) {
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate parallax helping variables
|
||||
var beforeTop = Math.max(0, contT),
|
||||
beforeTopEnd = Math.max(0, contH + contT),
|
||||
afterTop = Math.max(0, -contT),
|
||||
beforeBottom = Math.max(0, contT + contH - wndH),
|
||||
beforeBottomEnd = Math.max(0, contH - (contT + contH - wndH)),
|
||||
afterBottom = Math.max(0, -contT + wndH - contH),
|
||||
fromViewportCenter = 1 - 2 * (wndH - contT) / (wndH + contH);
|
||||
|
||||
// calculate on how percent of section is visible
|
||||
var visiblePercent = 1;
|
||||
if(contH < wndH) {
|
||||
visiblePercent = 1 - (afterTop || beforeBottom) / contH;
|
||||
} else {
|
||||
if(beforeTopEnd <= wndH) {
|
||||
visiblePercent = beforeTopEnd / wndH;
|
||||
} else if (beforeBottomEnd <= wndH) {
|
||||
visiblePercent = beforeBottomEnd / wndH;
|
||||
}
|
||||
}
|
||||
|
||||
// opacity
|
||||
if(_this.options.type === 'opacity' || _this.options.type === 'scale-opacity' || _this.options.type === 'scroll-opacity') {
|
||||
styles.transform = ''; // empty to add translateZ(0) where it is possible
|
||||
styles.opacity = visiblePercent;
|
||||
}
|
||||
|
||||
// scale
|
||||
if(_this.options.type === 'scale' || _this.options.type === 'scale-opacity') {
|
||||
var scale = 1;
|
||||
if(_this.options.speed < 0) {
|
||||
scale -= _this.options.speed * visiblePercent;
|
||||
} else {
|
||||
scale += _this.options.speed * (1 - visiblePercent);
|
||||
}
|
||||
styles.transform = 'scale(' + scale + ')';
|
||||
}
|
||||
|
||||
// scroll
|
||||
if(_this.options.type === 'scroll' || _this.options.type === 'scroll-opacity') {
|
||||
var positionY = _this.parallaxScrollDistance * fromViewportCenter;
|
||||
|
||||
// fix if parallax block in absolute position
|
||||
if(_this.image.position === 'absolute') {
|
||||
positionY -= contT;
|
||||
}
|
||||
|
||||
styles.transform = 'translateY(' + positionY + 'px)';
|
||||
}
|
||||
|
||||
_this.css(_this.image.$item, styles);
|
||||
|
||||
// call onScroll event
|
||||
if(_this.options.onScroll) {
|
||||
_this.options.onScroll.call(_this, {
|
||||
section: rect,
|
||||
|
||||
beforeTop: beforeTop,
|
||||
beforeTopEnd: beforeTopEnd,
|
||||
afterTop: afterTop,
|
||||
beforeBottom: beforeBottom,
|
||||
beforeBottomEnd: beforeBottomEnd,
|
||||
afterBottom: afterBottom,
|
||||
|
||||
visiblePercent: visiblePercent,
|
||||
fromViewportCenter: fromViewportCenter
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// init events
|
||||
function addEventListener (el, eventName, handler) {
|
||||
if (el.addEventListener) {
|
||||
el.addEventListener(eventName, handler);
|
||||
} else {
|
||||
el.attachEvent('on' + eventName, function (){
|
||||
handler.call(el);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function update (e) {
|
||||
window.requestAnimationFrame(function () {
|
||||
if(e.type !== 'scroll') {
|
||||
updateWndVars();
|
||||
}
|
||||
for(var k = 0, len = jarallaxList.length; k < len; k++) {
|
||||
// cover image and clip needed only when parallax container was changed
|
||||
if(e.type !== 'scroll') {
|
||||
jarallaxList[k].coverImage();
|
||||
jarallaxList[k].clipContainer();
|
||||
}
|
||||
jarallaxList[k].onScroll();
|
||||
}
|
||||
});
|
||||
}
|
||||
addEventListener(window, 'scroll', update);
|
||||
addEventListener(window, 'resize', update);
|
||||
addEventListener(window, 'orientationchange', update);
|
||||
addEventListener(window, 'load', update);
|
||||
|
||||
|
||||
// global definition
|
||||
var plugin = function (items) {
|
||||
// check for dom element
|
||||
// thanks: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
|
||||
if(typeof HTMLElement === "object" ? items instanceof HTMLElement : items && typeof items === "object" && items !== null && items.nodeType === 1 && typeof items.nodeName==="string") {
|
||||
items = [items];
|
||||
}
|
||||
|
||||
var options = arguments[1],
|
||||
args = Array.prototype.slice.call(arguments, 2),
|
||||
len = items.length,
|
||||
k = 0,
|
||||
ret;
|
||||
|
||||
for (k; k < len; k++) {
|
||||
if (typeof options === 'object' || typeof options === 'undefined') {
|
||||
if(!items[k].jarallax) {
|
||||
items[k].jarallax = new Jarallax(items[k], options);
|
||||
}
|
||||
}
|
||||
else if(items[k].jarallax) {
|
||||
ret = items[k].jarallax[options].apply(items[k].jarallax, args);
|
||||
}
|
||||
if (typeof ret !== 'undefined') {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
};
|
||||
plugin.constructor = Jarallax;
|
||||
|
||||
// no conflict
|
||||
var oldPlugin = window.jarallax;
|
||||
window.jarallax = plugin;
|
||||
window.jarallax.noConflict = function () {
|
||||
window.jarallax = oldPlugin;
|
||||
return this;
|
||||
};
|
||||
|
||||
// jQuery support
|
||||
if(typeof jQuery !== 'undefined') {
|
||||
var jQueryPlugin = function () {
|
||||
var args = arguments || [];
|
||||
Array.prototype.unshift.call(args, this);
|
||||
var res = plugin.apply(window, args);
|
||||
return typeof res !== 'object' ? res : this;
|
||||
};
|
||||
jQueryPlugin.constructor = Jarallax;
|
||||
|
||||
// no conflict
|
||||
var oldJqPlugin = jQuery.fn.jarallax;
|
||||
jQuery.fn.jarallax = jQueryPlugin;
|
||||
jQuery.fn.jarallax.noConflict = function () {
|
||||
jQuery.fn.jarallax = oldJqPlugin;
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
// data-jarallax initialization
|
||||
addEventListener(window, 'DOMContentLoaded', function () {
|
||||
plugin(document.querySelectorAll('[data-jarallax], [data-jarallax-video]'));
|
||||
});
|
||||
}(window));
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
|
||||
*
|
||||
* Uses the built in easing capabilities added In jQuery 1.1
|
||||
* to offer multiple easing options
|
||||
*
|
||||
* TERMS OF USE - jQuery Easing
|
||||
*
|
||||
* Open source under the BSD License.
|
||||
*
|
||||
* Copyright © 2008 George McGinley Smith
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the author nor the names of contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
// t: current time, b: begInnIng value, c: change In value, d: duration
|
||||
jQuery.easing['jswing'] = jQuery.easing['swing'];
|
||||
|
||||
jQuery.extend( jQuery.easing,
|
||||
{
|
||||
def: 'easeOutQuad',
|
||||
swing: function (x, t, b, c, d) {
|
||||
//alert(jQuery.easing.default);
|
||||
return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
|
||||
},
|
||||
easeInQuad: function (x, t, b, c, d) {
|
||||
return c*(t/=d)*t + b;
|
||||
},
|
||||
easeOutQuad: function (x, t, b, c, d) {
|
||||
return -c *(t/=d)*(t-2) + b;
|
||||
},
|
||||
easeInOutQuad: function (x, t, b, c, d) {
|
||||
if ((t/=d/2) < 1) return c/2*t*t + b;
|
||||
return -c/2 * ((--t)*(t-2) - 1) + b;
|
||||
},
|
||||
easeInCubic: function (x, t, b, c, d) {
|
||||
return c*(t/=d)*t*t + b;
|
||||
},
|
||||
easeOutCubic: function (x, t, b, c, d) {
|
||||
return c*((t=t/d-1)*t*t + 1) + b;
|
||||
},
|
||||
easeInOutCubic: function (x, t, b, c, d) {
|
||||
if ((t/=d/2) < 1) return c/2*t*t*t + b;
|
||||
return c/2*((t-=2)*t*t + 2) + b;
|
||||
},
|
||||
easeInQuart: function (x, t, b, c, d) {
|
||||
return c*(t/=d)*t*t*t + b;
|
||||
},
|
||||
easeOutQuart: function (x, t, b, c, d) {
|
||||
return -c * ((t=t/d-1)*t*t*t - 1) + b;
|
||||
},
|
||||
easeInOutQuart: function (x, t, b, c, d) {
|
||||
if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
|
||||
return -c/2 * ((t-=2)*t*t*t - 2) + b;
|
||||
},
|
||||
easeInQuint: function (x, t, b, c, d) {
|
||||
return c*(t/=d)*t*t*t*t + b;
|
||||
},
|
||||
easeOutQuint: function (x, t, b, c, d) {
|
||||
return c*((t=t/d-1)*t*t*t*t + 1) + b;
|
||||
},
|
||||
easeInOutQuint: function (x, t, b, c, d) {
|
||||
if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
|
||||
return c/2*((t-=2)*t*t*t*t + 2) + b;
|
||||
},
|
||||
easeInSine: function (x, t, b, c, d) {
|
||||
return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
|
||||
},
|
||||
easeOutSine: function (x, t, b, c, d) {
|
||||
return c * Math.sin(t/d * (Math.PI/2)) + b;
|
||||
},
|
||||
easeInOutSine: function (x, t, b, c, d) {
|
||||
return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
|
||||
},
|
||||
easeInExpo: function (x, t, b, c, d) {
|
||||
return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
|
||||
},
|
||||
easeOutExpo: function (x, t, b, c, d) {
|
||||
return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
|
||||
},
|
||||
easeInOutExpo: function (x, t, b, c, d) {
|
||||
if (t==0) return b;
|
||||
if (t==d) return b+c;
|
||||
if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
|
||||
return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
|
||||
},
|
||||
easeInCirc: function (x, t, b, c, d) {
|
||||
return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
|
||||
},
|
||||
easeOutCirc: function (x, t, b, c, d) {
|
||||
return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
|
||||
},
|
||||
easeInOutCirc: function (x, t, b, c, d) {
|
||||
if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
|
||||
return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
|
||||
},
|
||||
easeInElastic: function (x, t, b, c, d) {
|
||||
var s=1.70158;var p=0;var a=c;
|
||||
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
|
||||
if (a < Math.abs(c)) { a=c; var s=p/4; }
|
||||
else var s = p/(2*Math.PI) * Math.asin (c/a);
|
||||
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
|
||||
},
|
||||
easeOutElastic: function (x, t, b, c, d) {
|
||||
var s=1.70158;var p=0;var a=c;
|
||||
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
|
||||
if (a < Math.abs(c)) { a=c; var s=p/4; }
|
||||
else var s = p/(2*Math.PI) * Math.asin (c/a);
|
||||
return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
|
||||
},
|
||||
easeInOutElastic: function (x, t, b, c, d) {
|
||||
var s=1.70158;var p=0;var a=c;
|
||||
if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
|
||||
if (a < Math.abs(c)) { a=c; var s=p/4; }
|
||||
else var s = p/(2*Math.PI) * Math.asin (c/a);
|
||||
if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
|
||||
return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
|
||||
},
|
||||
easeInBack: function (x, t, b, c, d, s) {
|
||||
if (s == undefined) s = 1.70158;
|
||||
return c*(t/=d)*t*((s+1)*t - s) + b;
|
||||
},
|
||||
easeOutBack: function (x, t, b, c, d, s) {
|
||||
if (s == undefined) s = 1.70158;
|
||||
return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
|
||||
},
|
||||
easeInOutBack: function (x, t, b, c, d, s) {
|
||||
if (s == undefined) s = 1.70158;
|
||||
if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
|
||||
return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
|
||||
},
|
||||
easeInBounce: function (x, t, b, c, d) {
|
||||
return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
|
||||
},
|
||||
easeOutBounce: function (x, t, b, c, d) {
|
||||
if ((t/=d) < (1/2.75)) {
|
||||
return c*(7.5625*t*t) + b;
|
||||
} else if (t < (2/2.75)) {
|
||||
return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
|
||||
} else if (t < (2.5/2.75)) {
|
||||
return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
|
||||
} else {
|
||||
return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
|
||||
}
|
||||
},
|
||||
easeInOutBounce: function (x, t, b, c, d) {
|
||||
if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
|
||||
return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
*
|
||||
* TERMS OF USE - EASING EQUATIONS
|
||||
*
|
||||
* Open source under the BSD License.
|
||||
*
|
||||
* Copyright © 2001 Robert Penner
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the author nor the names of contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
Executable
+205
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
|
||||
*
|
||||
* Uses the built in easing capabilities added In jQuery 1.1
|
||||
* to offer multiple easing options
|
||||
*
|
||||
* TERMS OF USE - jQuery Easing
|
||||
*
|
||||
* Open source under the BSD License.
|
||||
*
|
||||
* Copyright © 2008 George McGinley Smith
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the author nor the names of contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
// t: current time, b: begInnIng value, c: change In value, d: duration
|
||||
jQuery.easing['jswing'] = jQuery.easing['swing'];
|
||||
|
||||
jQuery.extend( jQuery.easing,
|
||||
{
|
||||
def: 'easeOutQuad',
|
||||
swing: function (x, t, b, c, d) {
|
||||
//alert(jQuery.easing.default);
|
||||
return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
|
||||
},
|
||||
easeInQuad: function (x, t, b, c, d) {
|
||||
return c*(t/=d)*t + b;
|
||||
},
|
||||
easeOutQuad: function (x, t, b, c, d) {
|
||||
return -c *(t/=d)*(t-2) + b;
|
||||
},
|
||||
easeInOutQuad: function (x, t, b, c, d) {
|
||||
if ((t/=d/2) < 1) return c/2*t*t + b;
|
||||
return -c/2 * ((--t)*(t-2) - 1) + b;
|
||||
},
|
||||
easeInCubic: function (x, t, b, c, d) {
|
||||
return c*(t/=d)*t*t + b;
|
||||
},
|
||||
easeOutCubic: function (x, t, b, c, d) {
|
||||
return c*((t=t/d-1)*t*t + 1) + b;
|
||||
},
|
||||
easeInOutCubic: function (x, t, b, c, d) {
|
||||
if ((t/=d/2) < 1) return c/2*t*t*t + b;
|
||||
return c/2*((t-=2)*t*t + 2) + b;
|
||||
},
|
||||
easeInQuart: function (x, t, b, c, d) {
|
||||
return c*(t/=d)*t*t*t + b;
|
||||
},
|
||||
easeOutQuart: function (x, t, b, c, d) {
|
||||
return -c * ((t=t/d-1)*t*t*t - 1) + b;
|
||||
},
|
||||
easeInOutQuart: function (x, t, b, c, d) {
|
||||
if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
|
||||
return -c/2 * ((t-=2)*t*t*t - 2) + b;
|
||||
},
|
||||
easeInQuint: function (x, t, b, c, d) {
|
||||
return c*(t/=d)*t*t*t*t + b;
|
||||
},
|
||||
easeOutQuint: function (x, t, b, c, d) {
|
||||
return c*((t=t/d-1)*t*t*t*t + 1) + b;
|
||||
},
|
||||
easeInOutQuint: function (x, t, b, c, d) {
|
||||
if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
|
||||
return c/2*((t-=2)*t*t*t*t + 2) + b;
|
||||
},
|
||||
easeInSine: function (x, t, b, c, d) {
|
||||
return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
|
||||
},
|
||||
easeOutSine: function (x, t, b, c, d) {
|
||||
return c * Math.sin(t/d * (Math.PI/2)) + b;
|
||||
},
|
||||
easeInOutSine: function (x, t, b, c, d) {
|
||||
return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
|
||||
},
|
||||
easeInExpo: function (x, t, b, c, d) {
|
||||
return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
|
||||
},
|
||||
easeOutExpo: function (x, t, b, c, d) {
|
||||
return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
|
||||
},
|
||||
easeInOutExpo: function (x, t, b, c, d) {
|
||||
if (t==0) return b;
|
||||
if (t==d) return b+c;
|
||||
if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
|
||||
return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
|
||||
},
|
||||
easeInCirc: function (x, t, b, c, d) {
|
||||
return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
|
||||
},
|
||||
easeOutCirc: function (x, t, b, c, d) {
|
||||
return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
|
||||
},
|
||||
easeInOutCirc: function (x, t, b, c, d) {
|
||||
if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
|
||||
return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
|
||||
},
|
||||
easeInElastic: function (x, t, b, c, d) {
|
||||
var s=1.70158;var p=0;var a=c;
|
||||
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
|
||||
if (a < Math.abs(c)) { a=c; var s=p/4; }
|
||||
else var s = p/(2*Math.PI) * Math.asin (c/a);
|
||||
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
|
||||
},
|
||||
easeOutElastic: function (x, t, b, c, d) {
|
||||
var s=1.70158;var p=0;var a=c;
|
||||
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
|
||||
if (a < Math.abs(c)) { a=c; var s=p/4; }
|
||||
else var s = p/(2*Math.PI) * Math.asin (c/a);
|
||||
return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
|
||||
},
|
||||
easeInOutElastic: function (x, t, b, c, d) {
|
||||
var s=1.70158;var p=0;var a=c;
|
||||
if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
|
||||
if (a < Math.abs(c)) { a=c; var s=p/4; }
|
||||
else var s = p/(2*Math.PI) * Math.asin (c/a);
|
||||
if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
|
||||
return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
|
||||
},
|
||||
easeInBack: function (x, t, b, c, d, s) {
|
||||
if (s == undefined) s = 1.70158;
|
||||
return c*(t/=d)*t*((s+1)*t - s) + b;
|
||||
},
|
||||
easeOutBack: function (x, t, b, c, d, s) {
|
||||
if (s == undefined) s = 1.70158;
|
||||
return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
|
||||
},
|
||||
easeInOutBack: function (x, t, b, c, d, s) {
|
||||
if (s == undefined) s = 1.70158;
|
||||
if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
|
||||
return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
|
||||
},
|
||||
easeInBounce: function (x, t, b, c, d) {
|
||||
return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
|
||||
},
|
||||
easeOutBounce: function (x, t, b, c, d) {
|
||||
if ((t/=d) < (1/2.75)) {
|
||||
return c*(7.5625*t*t) + b;
|
||||
} else if (t < (2/2.75)) {
|
||||
return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
|
||||
} else if (t < (2.5/2.75)) {
|
||||
return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
|
||||
} else {
|
||||
return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
|
||||
}
|
||||
},
|
||||
easeInOutBounce: function (x, t, b, c, d) {
|
||||
if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
|
||||
return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
*
|
||||
* TERMS OF USE - EASING EQUATIONS
|
||||
*
|
||||
* Open source under the BSD License.
|
||||
*
|
||||
* Copyright © 2001 Robert Penner
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* Neither the name of the author nor the names of contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
+364
@@ -0,0 +1,364 @@
|
||||
/**!
|
||||
* easy-pie-chart
|
||||
* Lightweight plugin to render simple, animated and retina optimized pie charts
|
||||
*
|
||||
* @license
|
||||
* @author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de)
|
||||
* @version 2.1.7
|
||||
**/
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module unless amdModuleId is set
|
||||
define(["jquery"], function (a0) {
|
||||
return (factory(a0));
|
||||
});
|
||||
} 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 {
|
||||
factory(jQuery);
|
||||
}
|
||||
}(this, function ($) {
|
||||
|
||||
/**
|
||||
* Renderer to render the chart on a canvas object
|
||||
* @param {DOMElement} el DOM element to host the canvas (root of the plugin)
|
||||
* @param {object} options options object of the plugin
|
||||
*/
|
||||
var CanvasRenderer = function(el, options) {
|
||||
var cachedBackground;
|
||||
var canvas = document.createElement('canvas');
|
||||
|
||||
el.appendChild(canvas);
|
||||
|
||||
if (typeof(G_vmlCanvasManager) === 'object') {
|
||||
G_vmlCanvasManager.initElement(canvas);
|
||||
}
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
canvas.width = canvas.height = options.size;
|
||||
|
||||
// canvas on retina devices
|
||||
var scaleBy = 1;
|
||||
if (window.devicePixelRatio > 1) {
|
||||
scaleBy = window.devicePixelRatio;
|
||||
canvas.style.width = canvas.style.height = [options.size, 'px'].join('');
|
||||
canvas.width = canvas.height = options.size * scaleBy;
|
||||
ctx.scale(scaleBy, scaleBy);
|
||||
}
|
||||
|
||||
// move 0,0 coordinates to the center
|
||||
ctx.translate(options.size / 2, options.size / 2);
|
||||
|
||||
// rotate canvas -90deg
|
||||
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);
|
||||
|
||||
var radius = (options.size - options.lineWidth) / 2;
|
||||
if (options.scaleColor && options.scaleLength) {
|
||||
radius -= options.scaleLength + 2; // 2 is the distance between scale and bar
|
||||
}
|
||||
|
||||
// IE polyfill for Date
|
||||
Date.now = Date.now || function() {
|
||||
return +(new Date());
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw a circle around the center of the canvas
|
||||
* @param {strong} color Valid CSS color string
|
||||
* @param {number} lineWidth Width of the line in px
|
||||
* @param {number} percent Percentage to draw (float between -1 and 1)
|
||||
*/
|
||||
var drawCircle = function(color, lineWidth, percent) {
|
||||
percent = Math.min(Math.max(-1, percent || 0), 1);
|
||||
var isNegative = percent <= 0 ? true : false;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, isNegative);
|
||||
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = lineWidth;
|
||||
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw the scale of the chart
|
||||
*/
|
||||
var drawScale = function() {
|
||||
var offset;
|
||||
var length;
|
||||
|
||||
ctx.lineWidth = 1;
|
||||
ctx.fillStyle = options.scaleColor;
|
||||
|
||||
ctx.save();
|
||||
for (var i = 24; i > 0; --i) {
|
||||
if (i % 6 === 0) {
|
||||
length = options.scaleLength;
|
||||
offset = 0;
|
||||
} else {
|
||||
length = options.scaleLength * 0.6;
|
||||
offset = options.scaleLength - length;
|
||||
}
|
||||
ctx.fillRect(-options.size/2 + offset, 0, length, 1);
|
||||
ctx.rotate(Math.PI / 12);
|
||||
}
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
/**
|
||||
* Request animation frame wrapper with polyfill
|
||||
* @return {function} Request animation frame method or timeout fallback
|
||||
*/
|
||||
var reqAnimationFrame = (function() {
|
||||
return window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
function(callback) {
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
}());
|
||||
|
||||
/**
|
||||
* Draw the background of the plugin including the scale and the track
|
||||
*/
|
||||
var drawBackground = function() {
|
||||
if(options.scaleColor) drawScale();
|
||||
if(options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Canvas accessor
|
||||
*/
|
||||
this.getCanvas = function() {
|
||||
return canvas;
|
||||
};
|
||||
|
||||
/**
|
||||
* Canvas 2D context 'ctx' accessor
|
||||
*/
|
||||
this.getCtx = function() {
|
||||
return ctx;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the complete canvas
|
||||
*/
|
||||
this.clear = function() {
|
||||
ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size);
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw the complete chart
|
||||
* @param {number} percent Percent shown by the chart between -100 and 100
|
||||
*/
|
||||
this.draw = function(percent) {
|
||||
// do we need to render a background
|
||||
if (!!options.scaleColor || !!options.trackColor) {
|
||||
// getImageData and putImageData are supported
|
||||
if (ctx.getImageData && ctx.putImageData) {
|
||||
if (!cachedBackground) {
|
||||
drawBackground();
|
||||
cachedBackground = ctx.getImageData(0, 0, options.size * scaleBy, options.size * scaleBy);
|
||||
} else {
|
||||
ctx.putImageData(cachedBackground, 0, 0);
|
||||
}
|
||||
} else {
|
||||
this.clear();
|
||||
drawBackground();
|
||||
}
|
||||
} else {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
ctx.lineCap = options.lineCap;
|
||||
|
||||
// if barcolor is a function execute it and pass the percent as a value
|
||||
var color;
|
||||
if (typeof(options.barColor) === 'function') {
|
||||
color = options.barColor(percent);
|
||||
} else {
|
||||
color = options.barColor;
|
||||
}
|
||||
|
||||
// draw bar
|
||||
drawCircle(color, options.lineWidth, percent / 100);
|
||||
}.bind(this);
|
||||
|
||||
/**
|
||||
* Animate from some percent to some other percentage
|
||||
* @param {number} from Starting percentage
|
||||
* @param {number} to Final percentage
|
||||
*/
|
||||
this.animate = function(from, to) {
|
||||
var startTime = Date.now();
|
||||
options.onStart(from, to);
|
||||
var animation = function() {
|
||||
var process = Math.min(Date.now() - startTime, options.animate.duration);
|
||||
var currentValue = options.easing(this, process, from, to - from, options.animate.duration);
|
||||
this.draw(currentValue);
|
||||
options.onStep(from, to, currentValue);
|
||||
if (process >= options.animate.duration) {
|
||||
options.onStop(from, to);
|
||||
} else {
|
||||
reqAnimationFrame(animation);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
reqAnimationFrame(animation);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
var EasyPieChart = function(el, opts) {
|
||||
var defaultOptions = {
|
||||
barColor: '#ef1e25',
|
||||
trackColor: '#f9f9f9',
|
||||
scaleColor: '#dfe0e0',
|
||||
scaleLength: 5,
|
||||
lineCap: 'round',
|
||||
lineWidth: 3,
|
||||
trackWidth: undefined,
|
||||
size: 110,
|
||||
rotate: 0,
|
||||
animate: {
|
||||
duration: 1000,
|
||||
enabled: true
|
||||
},
|
||||
easing: function (x, t, b, c, d) { // more can be found here: http://gsgd.co.uk/sandbox/jquery/easing/
|
||||
t = t / (d/2);
|
||||
if (t < 1) {
|
||||
return c / 2 * t * t + b;
|
||||
}
|
||||
return -c/2 * ((--t)*(t-2) - 1) + b;
|
||||
},
|
||||
onStart: function(from, to) {
|
||||
return;
|
||||
},
|
||||
onStep: function(from, to, currentValue) {
|
||||
return;
|
||||
},
|
||||
onStop: function(from, to) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// detect present renderer
|
||||
if (typeof(CanvasRenderer) !== 'undefined') {
|
||||
defaultOptions.renderer = CanvasRenderer;
|
||||
} else if (typeof(SVGRenderer) !== 'undefined') {
|
||||
defaultOptions.renderer = SVGRenderer;
|
||||
} else {
|
||||
throw new Error('Please load either the SVG- or the CanvasRenderer');
|
||||
}
|
||||
|
||||
var options = {};
|
||||
var currentValue = 0;
|
||||
|
||||
/**
|
||||
* Initialize the plugin by creating the options object and initialize rendering
|
||||
*/
|
||||
var init = function() {
|
||||
this.el = el;
|
||||
this.options = options;
|
||||
|
||||
// merge user options into default options
|
||||
for (var i in defaultOptions) {
|
||||
if (defaultOptions.hasOwnProperty(i)) {
|
||||
options[i] = opts && typeof(opts[i]) !== 'undefined' ? opts[i] : defaultOptions[i];
|
||||
if (typeof(options[i]) === 'function') {
|
||||
options[i] = options[i].bind(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for jQuery easing
|
||||
if (typeof(options.easing) === 'string' && typeof(jQuery) !== 'undefined' && jQuery.isFunction(jQuery.easing[options.easing])) {
|
||||
options.easing = jQuery.easing[options.easing];
|
||||
} else {
|
||||
options.easing = defaultOptions.easing;
|
||||
}
|
||||
|
||||
// process earlier animate option to avoid bc breaks
|
||||
if (typeof(options.animate) === 'number') {
|
||||
options.animate = {
|
||||
duration: options.animate,
|
||||
enabled: true
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof(options.animate) === 'boolean' && !options.animate) {
|
||||
options.animate = {
|
||||
duration: 1000,
|
||||
enabled: options.animate
|
||||
};
|
||||
}
|
||||
|
||||
// create renderer
|
||||
this.renderer = new options.renderer(el, options);
|
||||
|
||||
// initial draw
|
||||
this.renderer.draw(currentValue);
|
||||
|
||||
// initial update
|
||||
if (el.dataset && el.dataset.percent) {
|
||||
this.update(parseFloat(el.dataset.percent));
|
||||
} else if (el.getAttribute && el.getAttribute('data-percent')) {
|
||||
this.update(parseFloat(el.getAttribute('data-percent')));
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
/**
|
||||
* Update the value of the chart
|
||||
* @param {number} newValue Number between 0 and 100
|
||||
* @return {object} Instance of the plugin for method chaining
|
||||
*/
|
||||
this.update = function(newValue) {
|
||||
newValue = parseFloat(newValue);
|
||||
if (options.animate.enabled) {
|
||||
this.renderer.animate(currentValue, newValue);
|
||||
} else {
|
||||
this.renderer.draw(newValue);
|
||||
}
|
||||
currentValue = newValue;
|
||||
return this;
|
||||
}.bind(this);
|
||||
|
||||
/**
|
||||
* Disable animation
|
||||
* @return {object} Instance of the plugin for method chaining
|
||||
*/
|
||||
this.disableAnimation = function() {
|
||||
options.animate.enabled = false;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Enable animation
|
||||
* @return {object} Instance of the plugin for method chaining
|
||||
*/
|
||||
this.enableAnimation = function() {
|
||||
options.animate.enabled = true;
|
||||
return this;
|
||||
};
|
||||
|
||||
init();
|
||||
};
|
||||
|
||||
$.fn.easyPieChart = function(options) {
|
||||
return this.each(function() {
|
||||
var instanceOptions;
|
||||
|
||||
if (!$.data(this, 'easyPieChart')) {
|
||||
instanceOptions = $.extend({}, options, $(this).data());
|
||||
$.data(this, 'easyPieChart', new EasyPieChart(this, instanceOptions));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
}));
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
(function(factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery', 'hammerjs'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
factory(require('jquery'), require('hammerjs'));
|
||||
} else {
|
||||
factory(jQuery, Hammer);
|
||||
}
|
||||
}(function($, Hammer) {
|
||||
function hammerify(el, options) {
|
||||
var $el = $(el);
|
||||
if(!$el.data("hammer")) {
|
||||
$el.data("hammer", new Hammer($el[0], options));
|
||||
}
|
||||
}
|
||||
|
||||
$.fn.hammer = function(options) {
|
||||
return this.each(function() {
|
||||
hammerify(this, options);
|
||||
});
|
||||
};
|
||||
|
||||
// extend the emit method to also trigger jQuery events
|
||||
Hammer.Manager.prototype.emit = (function(originalEmit) {
|
||||
return function(type, data) {
|
||||
originalEmit.call(this, type, data);
|
||||
$(this.element).trigger({
|
||||
type: type,
|
||||
gesture: data
|
||||
});
|
||||
};
|
||||
})(Hammer.Manager.prototype.emit);
|
||||
}));
|
||||
@@ -0,0 +1,98 @@
|
||||
/* jSticky Plugin
|
||||
* =============
|
||||
* Author: Andrew Henderson (@AndrewHenderson)
|
||||
* Date: 9/7/2012
|
||||
* Update: 02/14/2013
|
||||
* Website: http://github.com/andrewhenderson/jsticky/
|
||||
* Description: A jQuery plugin that keeps select DOM
|
||||
* element(s) in view while scrolling the page.
|
||||
*/
|
||||
|
||||
;(function($) {
|
||||
|
||||
$.fn.sticky = function(options) {
|
||||
|
||||
var defaults = {
|
||||
topSpacing: 0, // No spacing by default
|
||||
zIndex: '', // No default z-index
|
||||
stopper: '.sticky-stopper' // Default stopper class, also accepts number value
|
||||
},
|
||||
settings = $.extend({}, defaults, options); // Accepts custom stopper id or class
|
||||
|
||||
// Checks if custom z-index was defined
|
||||
function checkIndex() {
|
||||
|
||||
if (typeof settings.zIndex == 'number') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var hasIndex = checkIndex(); // True or false
|
||||
|
||||
// Checks if a stopper exists in the DOM or number defined
|
||||
function checkStopper() {
|
||||
|
||||
if ( 0 < $(settings.stopper).length || typeof settings.stopper === 'number' ) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var hasStopper = checkStopper(); // True or false
|
||||
|
||||
return this.each(function() {
|
||||
|
||||
var $this = $(this),
|
||||
thisHeight = $this.outerHeight(),
|
||||
thisWidth = $this.outerWidth(),
|
||||
topSpacing = settings.topSpacing,
|
||||
zIndex = settings.zIndex,
|
||||
pushPoint = $this.offset().top - topSpacing, // Point at which the sticky element starts pushing
|
||||
placeholder = $('<div></div>').width(thisWidth).height(thisHeight).addClass('sticky-placeholder'), // Cache a clone sticky element
|
||||
stopper = settings.stopper,
|
||||
$window = $(window);
|
||||
|
||||
function stickyScroll() {
|
||||
|
||||
var windowTop = $window.scrollTop(); // Check window's scroll position
|
||||
|
||||
if ( hasStopper && typeof stopper === 'string' ) {
|
||||
var stopperTop = $(stopper).offset().top,
|
||||
stopPoint = (stopperTop - thisHeight) - topSpacing;
|
||||
} else if (hasStopper && typeof stopper === 'number') {
|
||||
var stopPoint = stopper;
|
||||
}
|
||||
|
||||
if (pushPoint < windowTop) {
|
||||
// Create a placeholder for sticky element to occupy vertical real estate
|
||||
$this.after(placeholder).css({
|
||||
position: 'fixed',
|
||||
top: topSpacing
|
||||
});
|
||||
|
||||
if (hasIndex) {
|
||||
$this.css({ zIndex: zIndex });
|
||||
}
|
||||
|
||||
if (hasStopper) {
|
||||
if (stopPoint < windowTop) {
|
||||
var diff = (stopPoint - windowTop) + topSpacing;
|
||||
$this.css({ top: diff });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this.css({
|
||||
position: 'static',
|
||||
top: null,
|
||||
left: null
|
||||
});
|
||||
|
||||
placeholder.remove();
|
||||
}
|
||||
};
|
||||
|
||||
$window.bind("scroll", stickyScroll);
|
||||
});
|
||||
};
|
||||
})(jQuery);
|
||||
Executable
+117
@@ -0,0 +1,117 @@
|
||||
/* jSticky Plugin
|
||||
* =============
|
||||
* Author: Andrew Henderson (@AndrewHenderson)
|
||||
* Contributor: Mike Street (@mikestreety)
|
||||
* Date: 9/7/2012
|
||||
* Update: 09/20/2016
|
||||
* Website: http://github.com/andrewhenderson/jsticky/
|
||||
* Description: A jQuery plugin that keeps select DOM
|
||||
* element(s) in view while scrolling the page.
|
||||
*/
|
||||
|
||||
;(function($) {
|
||||
|
||||
$.fn.sticky = function(options) {
|
||||
var defaults = {
|
||||
topSpacing: 0, // No spacing by default
|
||||
zIndex: '', // No default z-index
|
||||
stopper: '.sticky-stopper', // Default stopper class, also accepts number value
|
||||
stickyClass: false // Class applied to element when it's stuck
|
||||
};
|
||||
var settings = $.extend({}, defaults, options); // Accepts custom stopper id or class
|
||||
|
||||
// Checks if custom z-index was defined
|
||||
function checkIndex() {
|
||||
if (typeof settings.zIndex == 'number') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var hasIndex = checkIndex(); // True or false
|
||||
|
||||
// Checks if a stopper exists in the DOM or number defined
|
||||
function checkStopper() {
|
||||
if (0 < $(settings.stopper).length || typeof settings.stopper === 'number') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var hasStopper = checkStopper(); // True or false
|
||||
|
||||
return this.each(function() {
|
||||
|
||||
var $this = $(this);
|
||||
var thisHeight = $this.outerHeight();
|
||||
var thisWidth = $this.outerWidth();
|
||||
var topSpacing = settings.topSpacing;
|
||||
var zIndex = settings.zIndex;
|
||||
var pushPoint = $this.offset().top - topSpacing; // Point at which the sticky element starts pushing
|
||||
var placeholder = $('<div></div>').width(thisWidth).height(thisHeight).addClass('sticky-placeholder'); // Cache a clone sticky element
|
||||
var stopper = settings.stopper;
|
||||
var $window = $(window);
|
||||
|
||||
function stickyScroll() {
|
||||
|
||||
var windowTop = $window.scrollTop(); // Check window's scroll position
|
||||
var stopPoint = stopper;
|
||||
var parentWidth = $this.parent().width();
|
||||
|
||||
placeholder.width(parentWidth)
|
||||
|
||||
if ( hasStopper && typeof stopper === 'string' ) {
|
||||
var stopperTop = $(stopper).offset().top;
|
||||
stopPoint = (stopperTop - thisHeight) - topSpacing;
|
||||
}
|
||||
|
||||
if (pushPoint < windowTop) {
|
||||
// Create a placeholder for sticky element to occupy vertical real estate
|
||||
if(settings.stickyClass)
|
||||
$this.addClass(settings.stickyClass);
|
||||
|
||||
$this.after(placeholder).css({
|
||||
position: 'fixed',
|
||||
top: topSpacing,
|
||||
width: parentWidth
|
||||
});
|
||||
|
||||
if (hasIndex) {
|
||||
$this.css({
|
||||
zIndex: zIndex
|
||||
});
|
||||
}
|
||||
|
||||
if (hasStopper) {
|
||||
if (stopPoint < windowTop) {
|
||||
var diff = (stopPoint - windowTop) + topSpacing;
|
||||
$this.css({
|
||||
top: diff
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(settings.stickyClass)
|
||||
$this.removeClass(settings.stickyClass);
|
||||
|
||||
$this.css({
|
||||
position: 'static',
|
||||
top: null,
|
||||
left: null,
|
||||
width: 'auto'
|
||||
});
|
||||
|
||||
placeholder.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if($window.innerHeight() > thisHeight) {
|
||||
|
||||
$window.bind('scroll', stickyScroll);
|
||||
$window.bind('load', stickyScroll);
|
||||
$window.bind('resize', stickyScroll);
|
||||
}
|
||||
});
|
||||
};
|
||||
})(jQuery);
|
||||
Executable
+1608
File diff suppressed because it is too large
Load Diff
+401
@@ -0,0 +1,401 @@
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
|
||||
$.fn.material_select = function (callback) {
|
||||
$(this).each(function () {
|
||||
var $select = $(this);
|
||||
|
||||
if ($select.hasClass('browser-default')) {
|
||||
return; // Continue to next (return false breaks out of entire loop)
|
||||
}
|
||||
|
||||
var multiple = Boolean($select.attr('multiple')),
|
||||
lastID = $select.data('select-id'); // Tear down structure if Select needs to be rebuilt
|
||||
|
||||
if (lastID) {
|
||||
$select.parent().find('span.caret').remove();
|
||||
$select.parent().find('input').remove();
|
||||
|
||||
$select.unwrap();
|
||||
$('ul#select-options-' + lastID).remove();
|
||||
}
|
||||
|
||||
// If destroying the select, remove the selelct-id and reset it to it's uninitialized state.
|
||||
if (callback === 'destroy') {
|
||||
$select.data('select-id', null).removeClass('initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
var uniqueID = guid(); // Materialize.guid();
|
||||
$select.data('select-id', uniqueID);
|
||||
var wrapper = $('<div class="select-wrapper"></div>');
|
||||
wrapper.addClass($select.attr('class'));
|
||||
var options = $('<ul id="select-options-' + uniqueID + '" class="dropdown-content select-dropdown ' + (multiple ? 'multiple-select-dropdown' : '') + '"></ul>'),
|
||||
selectChildren = $select.children('option, optgroup'),
|
||||
valuesSelected = [],
|
||||
optionsHover = false;
|
||||
|
||||
var label = $select.find('option:selected').html() || $select.find('option:first').html() || '';
|
||||
|
||||
// Added to search
|
||||
var applySeachInList = function applySeachInList() {
|
||||
|
||||
var ul = $(this).closest('ul');
|
||||
var searchValue = $(this).val();
|
||||
var options = ul.find('li').find('span.filtrable');
|
||||
|
||||
options.each(function () {
|
||||
if (typeof this.outerText === 'string') {
|
||||
var liValue = this.outerText.toLowerCase();
|
||||
|
||||
if (liValue.indexOf(searchValue.toLowerCase()) === -1) {
|
||||
$(this).hide();
|
||||
$(this).parent().hide();
|
||||
} else {
|
||||
$(this).show();
|
||||
$(this).parent().show();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Added to search
|
||||
var setSearchableOption = function setSearchableOption() {
|
||||
var placeholder = $select.attr('searchable');
|
||||
var element = $('<span class="search-wrap"><input type="text" class="search" placeholder="' + placeholder + '"></span>');
|
||||
options.append(element);
|
||||
element.find('.search').keyup(applySeachInList);
|
||||
};
|
||||
|
||||
// Added to search
|
||||
var searchable = Boolean($select.attr('searchable'));
|
||||
|
||||
// Added to search
|
||||
if (searchable) {
|
||||
setSearchableOption();
|
||||
}
|
||||
|
||||
// Function that renders and appends the option taking into
|
||||
// account type and possible image icon.
|
||||
var appendOptionWithIcon = function appendOptionWithIcon(select, option, type) {
|
||||
// Add disabled attr if disabled
|
||||
var disabledClass = option.is(':disabled') ? 'disabled ' : '';
|
||||
var optgroupClass = type === 'optgroup-option' ? 'optgroup-option ' : '';
|
||||
|
||||
// add icons
|
||||
var icon_url = option.data('icon');
|
||||
var classes = option.attr('class');
|
||||
if (icon_url) {
|
||||
var classString = '';
|
||||
if (classes) {
|
||||
classString = ' class="' + classes + '"';
|
||||
}
|
||||
|
||||
// Check for multiple type.
|
||||
if (type === 'multiple') {
|
||||
options.append($('<li class="' + disabledClass + '"><img alt="" src="' + icon_url + '"' + classString + '><span class="filtrable"><input type="checkbox"' + disabledClass + '/><label></label>' + option.html() + '</span></li>'));
|
||||
} else {
|
||||
options.append($('<li class="' + disabledClass + optgroupClass + '"><img alt="" src="' + icon_url + '"' + classString + '><span class="filtrable">' + option.html() + '</span></li>'));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for multiple type.
|
||||
if (type === 'multiple') {
|
||||
options.append($('<li class="' + disabledClass + '"><span class="filtrable"><input type="checkbox"' + disabledClass + '/><label></label>' + option.html() + '</span></li>'));
|
||||
} else {
|
||||
options.append($('<li class="' + disabledClass + optgroupClass + '"><span class="filtrable">' + option.html() + '</span></li>'));
|
||||
}
|
||||
};
|
||||
|
||||
/* Create dropdown structure. */
|
||||
if (selectChildren.length) {
|
||||
selectChildren.each(function () {
|
||||
if ($(this).is('option')) {
|
||||
// Direct descendant option.
|
||||
if (multiple) {
|
||||
appendOptionWithIcon($select, $(this), 'multiple');
|
||||
} else {
|
||||
appendOptionWithIcon($select, $(this));
|
||||
}
|
||||
} else if ($(this).is('optgroup')) {
|
||||
// Optgroup.
|
||||
var selectOptions = $(this).children('option');
|
||||
options.append($('<li class="optgroup"><span>' + $(this).attr('label') + '</span></li>'));
|
||||
|
||||
selectOptions.each(function () {
|
||||
appendOptionWithIcon($select, $(this), 'optgroup-option');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
options.find('li:not(.optgroup)').each(function (i) {
|
||||
$(this).click(function (e) {
|
||||
// Check if option element is disabled
|
||||
if (!$(this).hasClass('disabled') && !$(this).hasClass('optgroup')) {
|
||||
var selected = true;
|
||||
|
||||
if (multiple) {
|
||||
$('input[type="checkbox"]', this).prop('checked', function (i, v) {
|
||||
return !v;
|
||||
});
|
||||
selected = toggleEntryFromArray(valuesSelected, $(this).index() - 1, $select);
|
||||
$newSelect.trigger('focus');
|
||||
} else {
|
||||
options.find('li').removeClass('active');
|
||||
$(this).toggleClass('active');
|
||||
$newSelect.val($(this).text());
|
||||
}
|
||||
|
||||
activateOption(options, $(this));
|
||||
$select.find('option').eq(i).prop('selected', selected);
|
||||
// Trigger onchange() event
|
||||
$select.trigger('change');
|
||||
if (typeof callback !== 'undefined') {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
|
||||
// Wrap Elements
|
||||
$select.wrap(wrapper);
|
||||
// Add Select Display Element
|
||||
var dropdownIcon = $('<span class="caret">▼</span>');
|
||||
if ($select.is(':disabled')) {
|
||||
dropdownIcon.addClass('disabled');
|
||||
}
|
||||
|
||||
// escape double quotes
|
||||
var sanitizedLabelHtml = label.replace(/"/g, '"');
|
||||
|
||||
var $newSelect = $('<input type="text" class="select-dropdown" readonly="true" ' + ($select.is(':disabled') ? 'disabled' : '') + ' data-activates="select-options-' + uniqueID + '" value="' + sanitizedLabelHtml + '"/>');
|
||||
$select.before($newSelect);
|
||||
$newSelect.before(dropdownIcon);
|
||||
|
||||
$newSelect.after(options);
|
||||
// Check if section element is disabled
|
||||
if (!$select.is(':disabled')) {
|
||||
$newSelect.dropdown({
|
||||
hover: false,
|
||||
closeOnClick: false
|
||||
});
|
||||
}
|
||||
|
||||
// Copy tabindex
|
||||
if ($select.attr('tabindex')) {
|
||||
$($newSelect[0]).attr('tabindex', $select.attr('tabindex'));
|
||||
}
|
||||
|
||||
$select.addClass('initialized');
|
||||
|
||||
$newSelect.on({
|
||||
focus: function focus() {
|
||||
if ($('ul.select-dropdown').not(options[0]).is(':visible')) {
|
||||
$('input.select-dropdown').trigger('close');
|
||||
}
|
||||
if (!options.is(':visible')) {
|
||||
$(this).trigger('open', ['focus']);
|
||||
var _label = $(this).val();
|
||||
var selectedOption = options.find('li').filter(function () {
|
||||
return $(this).text().toLowerCase() === _label.toLowerCase();
|
||||
})[0];
|
||||
activateOption(options, selectedOption);
|
||||
}
|
||||
},
|
||||
click: function click(e) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
// Changed to search to treat search
|
||||
$newSelect.on('blur', function () {
|
||||
|
||||
if (!multiple && !searchable) {
|
||||
$(this).trigger('close');
|
||||
}
|
||||
options.find('li.selected').removeClass('selected');
|
||||
});
|
||||
|
||||
// Added to search
|
||||
if (!multiple && searchable) {
|
||||
options.find('li').on('click', function () {
|
||||
$newSelect.trigger('close');
|
||||
});
|
||||
}
|
||||
|
||||
options.hover(function () {
|
||||
optionsHover = true;
|
||||
}, function () {
|
||||
optionsHover = false;
|
||||
});
|
||||
|
||||
// Changed to search to treat search
|
||||
$(window).on({
|
||||
click: function click() {
|
||||
(multiple || searchable) && (optionsHover || $newSelect.trigger('close'));
|
||||
}
|
||||
});
|
||||
|
||||
// Add initial multiple selections.
|
||||
if (multiple) {
|
||||
$select.find('option:selected:not(:disabled)').each(function () {
|
||||
var index = $(this).index();
|
||||
|
||||
toggleEntryFromArray(valuesSelected, index, $select);
|
||||
options.find('li').eq(index).find(':checkbox').prop('checked', true);
|
||||
});
|
||||
}
|
||||
|
||||
// Make option as selected and scroll to selected position
|
||||
var activateOption = function activateOption(collection, newOption) {
|
||||
if (newOption) {
|
||||
collection.find('li.selected').removeClass('selected');
|
||||
var option = $(newOption);
|
||||
option.addClass('selected');
|
||||
// commented because it causes problems in multiselect with many options
|
||||
// options.scrollTo(option)
|
||||
}
|
||||
};
|
||||
|
||||
// Allow user to search by typing
|
||||
// this array is cleared after 1 second
|
||||
var filterQuery = [],
|
||||
onKeyDown = function onKeyDown(e) {
|
||||
// TAB - switch to another input
|
||||
if (e.which == 9) {
|
||||
$newSelect.trigger('close');
|
||||
return;
|
||||
}
|
||||
|
||||
// ARROW DOWN WHEN SELECT IS CLOSED - open select options
|
||||
if (e.which == 40 && !options.is(':visible')) {
|
||||
$newSelect.trigger('open');
|
||||
return;
|
||||
}
|
||||
|
||||
// ENTER WHEN SELECT IS CLOSED - submit form
|
||||
if (e.which == 13 && !options.is(':visible')) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// CASE WHEN USER TYPE LETTERS
|
||||
var letter = String.fromCharCode(e.which).toLowerCase(),
|
||||
nonLetters = [9, 13, 27, 38, 40];
|
||||
if (letter && nonLetters.indexOf(e.which) === -1) {
|
||||
filterQuery.push(letter);
|
||||
|
||||
var string = filterQuery.join(''),
|
||||
newOption = options.find('li').filter(function () {
|
||||
return $(this).text().toLowerCase().indexOf(string) === 0;
|
||||
})[0];
|
||||
|
||||
if (newOption) {
|
||||
activateOption(options, newOption);
|
||||
}
|
||||
}
|
||||
|
||||
// ENTER - select option and close when select options are opened
|
||||
if (e.which == 13) {
|
||||
var activeOption = options.find('li.selected:not(.disabled)')[0];
|
||||
if (activeOption) {
|
||||
$(activeOption).trigger('click');
|
||||
if (!multiple) {
|
||||
$newSelect.trigger('close');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ARROW DOWN - move to next not disabled option
|
||||
if (e.which == 40) {
|
||||
if (options.find('li.selected').length) {
|
||||
newOption = options.find('li.selected').next('li:not(.disabled)')[0];
|
||||
} else {
|
||||
newOption = options.find('li:not(.disabled)')[0];
|
||||
}
|
||||
activateOption(options, newOption);
|
||||
}
|
||||
|
||||
// ESC - close options
|
||||
if (e.which == 27) {
|
||||
$newSelect.trigger('close');
|
||||
}
|
||||
|
||||
// ARROW UP - move to previous not disabled option
|
||||
if (e.which == 38) {
|
||||
newOption = options.find('li.selected').prev('li:not(.disabled)')[0];
|
||||
if (newOption) {
|
||||
activateOption(options, newOption);
|
||||
}
|
||||
}
|
||||
|
||||
// Automaticaly clean filter query so user can search again by starting letters
|
||||
setTimeout(function () {
|
||||
filterQuery = [];
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
$newSelect.on('keydown', onKeyDown);
|
||||
});
|
||||
|
||||
function toggleEntryFromArray(entriesArray, entryIndex, select) {
|
||||
var index = entriesArray.indexOf(entryIndex),
|
||||
notAdded = index === -1;
|
||||
|
||||
if (notAdded) {
|
||||
entriesArray.push(entryIndex);
|
||||
} else {
|
||||
entriesArray.splice(index, 1);
|
||||
}
|
||||
|
||||
select.siblings('ul.dropdown-content').find('li').eq(entryIndex).toggleClass('active');
|
||||
|
||||
// use notAdded instead of true (to detect if the option is selected or not)
|
||||
select.find('option').eq(entryIndex).prop('selected', notAdded);
|
||||
setValueToInput(entriesArray, select);
|
||||
|
||||
return notAdded;
|
||||
}
|
||||
|
||||
function setValueToInput(entriesArray, select) {
|
||||
var value = '';
|
||||
|
||||
for (var i = 0, count = entriesArray.length; i < count; i++) {
|
||||
var text = select.find('option').eq(entriesArray[i]).text();
|
||||
|
||||
i === 0 ? value += text : value += ', ' + text;
|
||||
}
|
||||
|
||||
if (value === '') {
|
||||
value = select.find('option:disabled').eq(0).text();
|
||||
}
|
||||
|
||||
select.siblings('input.select-dropdown').val(value);
|
||||
}
|
||||
// };
|
||||
|
||||
function guid() {
|
||||
var d = new Date().getTime();
|
||||
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||
var r = (d + Math.random() * 16) % 16 | 0;
|
||||
d = Math.floor(d / 16);
|
||||
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
||||
});
|
||||
return uuid;
|
||||
}
|
||||
};
|
||||
})(jQuery);
|
||||
|
||||
jQuery('select').siblings('input.select-dropdown').on('mousedown', function (e) {
|
||||
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
|
||||
if (e.clientX >= e.target.clientWidth || e.clientY >= e.target.clientHeight) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* Material Design for Bootstrap
|
||||
* MDB Autocomplete Plugin
|
||||
*/
|
||||
|
||||
$.fn.mdb_autocomplete = function (options) {
|
||||
|
||||
// Default options
|
||||
var defaults = {
|
||||
data: {}
|
||||
};
|
||||
|
||||
var ENTER_CHAR_CODE = 13;
|
||||
|
||||
// Get options
|
||||
options = $.extend(defaults, options);
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
// text input
|
||||
var $input = $(this);
|
||||
var $autocomplete = void 0;
|
||||
|
||||
// assign data from options
|
||||
var data = options.data;
|
||||
|
||||
if (Object.keys(data).length) {
|
||||
|
||||
$autocomplete = $('<ul class="mdb-autocomplete-wrap"></ul>');
|
||||
|
||||
$autocomplete.insertAfter($(this));
|
||||
};
|
||||
|
||||
// Listen if key was pressed
|
||||
$input.on('keyup', function (e) {
|
||||
|
||||
// get value from input
|
||||
var q = $input.val();
|
||||
|
||||
$autocomplete.empty();
|
||||
|
||||
// check if input isn't empty
|
||||
if (q.length) {
|
||||
|
||||
for (var item in data) {
|
||||
|
||||
// check if item contains value that we're looking for
|
||||
if (data[item].toLowerCase().indexOf(q.toLowerCase()) !== -1) {
|
||||
var option = $('<li>' + data[item] + '</li>');
|
||||
|
||||
$autocomplete.append(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (e.which === ENTER_CHAR_CODE) {
|
||||
$autocomplete.children(":first").trigger('click');
|
||||
$autocomplete.empty();
|
||||
}
|
||||
|
||||
if (q.length === 0) {
|
||||
$('.mdb-autocomplete-clear').css('visibility', 'hidden');
|
||||
} else {
|
||||
$('.mdb-autocomplete-clear').css('visibility', 'visible');
|
||||
}
|
||||
});
|
||||
|
||||
$autocomplete.on('click', 'li', function () {
|
||||
|
||||
// Set input value after click
|
||||
$input.val($(this).text());
|
||||
|
||||
// Clear autocomplete
|
||||
$autocomplete.empty();
|
||||
});
|
||||
|
||||
$('.mdb-autocomplete-clear').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$input.val('');
|
||||
$(this).css('visibility', 'hidden');
|
||||
$autocomplete.empty();
|
||||
$(this).parent().find('label').removeClass('active');
|
||||
});
|
||||
});
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
|
||||
//Collapse other tabs for popout
|
||||
$(function () {
|
||||
var active = true;
|
||||
|
||||
$('#accordion').on('show.bs.collapse', function () {
|
||||
if (active) $('#accordion .in').collapse('hide');
|
||||
});
|
||||
|
||||
});
|
||||
Executable
+1380
File diff suppressed because it is too large
Load Diff
Executable
+699
@@ -0,0 +1,699 @@
|
||||
/*!
|
||||
* ClockPicker v0.0.7 (http://weareoutman.github.io/clockpicker/)
|
||||
* Copyright 2014 Wang Shenwei.
|
||||
* Licensed under MIT (https://github.com/weareoutman/clockpicker/blob/gh-pages/LICENSE)
|
||||
*
|
||||
* Further modified
|
||||
* Copyright 2015 Ching Yaw Hao.
|
||||
*/
|
||||
|
||||
;(function(){
|
||||
var $ = window.jQuery,
|
||||
$win = $(window),
|
||||
$doc = $(document);
|
||||
|
||||
// Can I use inline svg ?
|
||||
var svgNS = 'http://www.w3.org/2000/svg',
|
||||
svgSupported = 'SVGAngle' in window && (function() {
|
||||
var supported,
|
||||
el = document.createElement('div');
|
||||
el.innerHTML = '<svg/>';
|
||||
supported = (el.firstChild && el.firstChild.namespaceURI) == svgNS;
|
||||
el.innerHTML = '';
|
||||
return supported;
|
||||
})();
|
||||
|
||||
// Can I use transition ?
|
||||
var transitionSupported = (function() {
|
||||
var style = document.createElement('div').style;
|
||||
return 'transition' in style ||
|
||||
'WebkitTransition' in style ||
|
||||
'MozTransition' in style ||
|
||||
'msTransition' in style ||
|
||||
'OTransition' in style;
|
||||
})();
|
||||
|
||||
// Listen touch events in touch screen device, instead of mouse events in desktop.
|
||||
var touchSupported = 'ontouchstart' in window,
|
||||
mousedownEvent = 'mousedown' + ( touchSupported ? ' touchstart' : ''),
|
||||
mousemoveEvent = 'mousemove.clockpicker' + ( touchSupported ? ' touchmove.clockpicker' : ''),
|
||||
mouseupEvent = 'mouseup.clockpicker' + ( touchSupported ? ' touchend.clockpicker' : '');
|
||||
|
||||
// Vibrate the device if supported
|
||||
var vibrate = navigator.vibrate ? 'vibrate' : navigator.webkitVibrate ? 'webkitVibrate' : null;
|
||||
|
||||
function createSvgElement(name) {
|
||||
return document.createElementNS(svgNS, name);
|
||||
}
|
||||
|
||||
function leadingZero(num) {
|
||||
return (num < 10 ? '0' : '') + num;
|
||||
}
|
||||
|
||||
// Get a unique id
|
||||
var idCounter = 0;
|
||||
function uniqueId(prefix) {
|
||||
var id = ++idCounter + '';
|
||||
return prefix ? prefix + id : id;
|
||||
}
|
||||
|
||||
// Clock size
|
||||
var dialRadius = 135,
|
||||
outerRadius = 110,
|
||||
// innerRadius = 80 on 12 hour clock
|
||||
innerRadius = 80,
|
||||
tickRadius = 20,
|
||||
diameter = dialRadius * 2,
|
||||
duration = transitionSupported ? 350 : 1;
|
||||
|
||||
// Popover template
|
||||
var tpl = [
|
||||
'<div class="clockpicker picker">',
|
||||
'<div class="picker__holder">',
|
||||
'<div class="picker__frame">',
|
||||
'<div class="picker__wrap">',
|
||||
'<div class="picker__box">',
|
||||
'<div class="picker__date-display">',
|
||||
'<div class="clockpicker-display">',
|
||||
'<div class="clockpicker-display-column">',
|
||||
'<span class="clockpicker-span-hours text-primary"></span>',
|
||||
':',
|
||||
'<span class="clockpicker-span-minutes"></span>',
|
||||
'</div>',
|
||||
'<div class="clockpicker-display-column clockpicker-display-am-pm">',
|
||||
'<div class="clockpicker-span-am-pm"></div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="picker__calendar-container">',
|
||||
'<div class="clockpicker-plate">',
|
||||
'<div class="clockpicker-canvas"></div>',
|
||||
'<div class="clockpicker-dial clockpicker-hours"></div>',
|
||||
'<div class="clockpicker-dial clockpicker-minutes clockpicker-dial-out"></div>',
|
||||
'</div>',
|
||||
'<div class="clockpicker-am-pm-block">',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="picker__footer">',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
// ClockPicker
|
||||
function ClockPicker(element, options) {
|
||||
var popover = $(tpl),
|
||||
plate = popover.find('.clockpicker-plate'),
|
||||
holder = popover.find('.picker__holder'),
|
||||
hoursView = popover.find('.clockpicker-hours'),
|
||||
minutesView = popover.find('.clockpicker-minutes'),
|
||||
amPmBlock = popover.find('.clockpicker-am-pm-block'),
|
||||
isInput = element.prop('tagName') === 'INPUT',
|
||||
input = isInput ? element : element.find('input'),
|
||||
label = $("label[for=" + input.attr("id") + "]"),
|
||||
self = this,
|
||||
timer;
|
||||
|
||||
this.id = uniqueId('cp');
|
||||
this.element = element;
|
||||
this.holder = holder;
|
||||
this.options = options;
|
||||
this.isAppended = false;
|
||||
this.isShown = false;
|
||||
this.currentView = 'hours';
|
||||
this.isInput = isInput;
|
||||
this.input = input;
|
||||
this.label = label;
|
||||
this.popover = popover;
|
||||
this.plate = plate;
|
||||
this.hoursView = hoursView;
|
||||
this.minutesView = minutesView;
|
||||
this.amPmBlock = amPmBlock;
|
||||
this.spanHours = popover.find('.clockpicker-span-hours');
|
||||
this.spanMinutes = popover.find('.clockpicker-span-minutes');
|
||||
this.spanAmPm = popover.find('.clockpicker-span-am-pm');
|
||||
this.footer = popover.find('.picker__footer');
|
||||
this.amOrPm = "PM";
|
||||
|
||||
// Setup for for 12 hour clock if option is selected
|
||||
if (options.twelvehour) {
|
||||
var amPmButtonsTemplate = [
|
||||
'<div class="clockpicker-am-pm-block">',
|
||||
'<button type="button" class="btn-floating btn-flat clockpicker-button clockpicker-am-button">',
|
||||
'AM',
|
||||
'</button>',
|
||||
'<button type="button" class="btn-floating btn-flat clockpicker-button clockpicker-pm-button">',
|
||||
'PM',
|
||||
'</button>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
var amPmButtons = $(amPmButtonsTemplate);
|
||||
|
||||
if(!options.ampmclickable) {
|
||||
$('<button type="button" class="btn-floating btn-flat clockpicker-button am-button" tabindex="1">' + "AM" + '</button>').on("click", function() {
|
||||
self.amOrPm = "AM";
|
||||
self.amPmBlock.children('.pm-button').removeClass('active');
|
||||
self.amPmBlock.children('.am-button').addClass('active');
|
||||
self.spanAmPm.empty().append('AM');
|
||||
}).appendTo(this.amPmBlock);
|
||||
$('<button type="button" class="btn-floating btn-flat clockpicker-button pm-button" tabindex="2">' + "PM" + '</button>').on("click", function() {
|
||||
self.amOrPm = 'PM';
|
||||
self.amPmBlock.children('.am-button').removeClass('active');
|
||||
self.amPmBlock.children('.pm-button').addClass('active');
|
||||
self.spanAmPm.empty().append('PM');
|
||||
}).appendTo(this.amPmBlock);
|
||||
}
|
||||
else {
|
||||
this.spanAmPm.empty();
|
||||
$('<div id="click-am">AM</div>').on("click", function() {
|
||||
self.spanAmPm.children('#click-am').addClass("text-primary");
|
||||
self.spanAmPm.children('#click-pm').removeClass("text-primary");
|
||||
self.amOrPm = "AM";
|
||||
}).appendTo(this.spanAmPm);
|
||||
$('<div id="click-pm">PM</div>').on("click", function() {
|
||||
self.spanAmPm.children('#click-pm').addClass("text-primary");
|
||||
self.spanAmPm.children('#click-am').removeClass("text-primary");
|
||||
self.amOrPm = 'PM';
|
||||
}).appendTo(this.spanAmPm);
|
||||
}
|
||||
}
|
||||
|
||||
if(options.darktheme)
|
||||
popover.addClass('darktheme');
|
||||
|
||||
// If autoclose is not setted, append a button
|
||||
$('<button type="button" class="btn-flat clockpicker-button" tabindex="' + (options.twelvehour? '3' : '1') + '">' + options.donetext + '</button>').click($.proxy(this.done, this)).appendTo(this.footer);
|
||||
|
||||
this.spanHours.click($.proxy(this.toggleView, this, 'hours'));
|
||||
this.spanMinutes.click($.proxy(this.toggleView, this, 'minutes'));
|
||||
|
||||
// Show or toggle
|
||||
input.on('focus.clockpicker click.clockpicker', $.proxy(this.show, this));
|
||||
|
||||
// Build ticks
|
||||
var tickTpl = $('<div class="clockpicker-tick"></div>'),
|
||||
i, tick, radian, radius;
|
||||
|
||||
// Hours view
|
||||
if (options.twelvehour) {
|
||||
for (i = 1; i < 13; i += 1) {
|
||||
tick = tickTpl.clone();
|
||||
radian = i / 6 * Math.PI;
|
||||
radius = outerRadius;
|
||||
tick.css('font-size', '140%');
|
||||
tick.css({
|
||||
left: dialRadius + Math.sin(radian) * radius - tickRadius,
|
||||
top: dialRadius - Math.cos(radian) * radius - tickRadius
|
||||
});
|
||||
tick.html(i === 0 ? '00' : i);
|
||||
hoursView.append(tick);
|
||||
tick.on(mousedownEvent, mousedown);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 24; i += 1) {
|
||||
tick = tickTpl.clone();
|
||||
radian = i / 6 * Math.PI;
|
||||
var inner = i > 0 && i < 13;
|
||||
radius = inner ? innerRadius : outerRadius;
|
||||
tick.css({
|
||||
left: dialRadius + Math.sin(radian) * radius - tickRadius,
|
||||
top: dialRadius - Math.cos(radian) * radius - tickRadius
|
||||
});
|
||||
if (inner)
|
||||
tick.css('font-size', '120%');
|
||||
tick.html(i === 0 ? '00' : i);
|
||||
hoursView.append(tick);
|
||||
tick.on(mousedownEvent, mousedown);
|
||||
}
|
||||
}
|
||||
|
||||
// Minutes view
|
||||
for (i = 0; i < 60; i += 5) {
|
||||
tick = tickTpl.clone();
|
||||
radian = i / 30 * Math.PI;
|
||||
tick.css({
|
||||
left: dialRadius + Math.sin(radian) * outerRadius - tickRadius,
|
||||
top: dialRadius - Math.cos(radian) * outerRadius - tickRadius
|
||||
});
|
||||
tick.css('font-size', '140%');
|
||||
tick.html(leadingZero(i));
|
||||
minutesView.append(tick);
|
||||
tick.on(mousedownEvent, mousedown);
|
||||
}
|
||||
|
||||
// Clicking on minutes view space
|
||||
plate.on(mousedownEvent, function(e) {
|
||||
if ($(e.target).closest('.clockpicker-tick').length === 0)
|
||||
mousedown(e, true);
|
||||
});
|
||||
|
||||
// Mousedown or touchstart
|
||||
function mousedown(e, space) {
|
||||
var offset = plate.offset(),
|
||||
isTouch = /^touch/.test(e.type),
|
||||
x0 = offset.left + dialRadius,
|
||||
y0 = offset.top + dialRadius,
|
||||
dx = (isTouch ? e.originalEvent.touches[0] : e).pageX - x0,
|
||||
dy = (isTouch ? e.originalEvent.touches[0] : e).pageY - y0,
|
||||
z = Math.sqrt(dx * dx + dy * dy),
|
||||
moved = false;
|
||||
|
||||
// When clicking on minutes view space, check the mouse position
|
||||
if (space && (z < outerRadius - tickRadius || z > outerRadius + tickRadius))
|
||||
return;
|
||||
e.preventDefault();
|
||||
|
||||
// Set cursor style of body after 200ms
|
||||
var movingTimer = setTimeout(function(){
|
||||
self.popover.addClass('clockpicker-moving');
|
||||
}, 200);
|
||||
|
||||
// Place the canvas to top
|
||||
if (svgSupported)
|
||||
plate.append(self.canvas);
|
||||
|
||||
// Clock
|
||||
self.setHand(dx, dy, !space, true);
|
||||
|
||||
// Mousemove on document
|
||||
$doc.off(mousemoveEvent).on(mousemoveEvent, function(e){
|
||||
e.preventDefault();
|
||||
var isTouch = /^touch/.test(e.type),
|
||||
x = (isTouch ? e.originalEvent.touches[0] : e).pageX - x0,
|
||||
y = (isTouch ? e.originalEvent.touches[0] : e).pageY - y0;
|
||||
if (! moved && x === dx && y === dy)
|
||||
// Clicking in chrome on windows will trigger a mousemove event
|
||||
return;
|
||||
moved = true;
|
||||
self.setHand(x, y, false, true);
|
||||
});
|
||||
|
||||
// Mouseup on document
|
||||
$doc.off(mouseupEvent).on(mouseupEvent, function(e) {
|
||||
$doc.off(mouseupEvent);
|
||||
e.preventDefault();
|
||||
var isTouch = /^touch/.test(e.type),
|
||||
x = (isTouch ? e.originalEvent.changedTouches[0] : e).pageX - x0,
|
||||
y = (isTouch ? e.originalEvent.changedTouches[0] : e).pageY - y0;
|
||||
if ((space || moved) && x === dx && y === dy)
|
||||
self.setHand(x, y);
|
||||
if (self.currentView === 'hours')
|
||||
self.toggleView('minutes', duration / 2);
|
||||
else
|
||||
if (options.autoclose) {
|
||||
self.minutesView.addClass('clockpicker-dial-out');
|
||||
setTimeout(function(){
|
||||
self.done();
|
||||
}, duration / 2);
|
||||
}
|
||||
plate.prepend(canvas);
|
||||
|
||||
// Reset cursor style of body
|
||||
clearTimeout(movingTimer);
|
||||
self.popover.removeClass('clockpicker-moving');
|
||||
|
||||
// Unbind mousemove event
|
||||
$doc.off(mousemoveEvent);
|
||||
});
|
||||
}
|
||||
|
||||
if (svgSupported) {
|
||||
// Draw clock hands and others
|
||||
var canvas = popover.find('.clockpicker-canvas'),
|
||||
svg = createSvgElement('svg');
|
||||
svg.setAttribute('class', 'clockpicker-svg');
|
||||
svg.setAttribute('width', diameter);
|
||||
svg.setAttribute('height', diameter);
|
||||
var g = createSvgElement('g');
|
||||
g.setAttribute('transform', 'translate(' + dialRadius + ',' + dialRadius + ')');
|
||||
var bearing = createSvgElement('circle');
|
||||
bearing.setAttribute('class', 'clockpicker-canvas-bearing');
|
||||
bearing.setAttribute('cx', 0);
|
||||
bearing.setAttribute('cy', 0);
|
||||
bearing.setAttribute('r', 2);
|
||||
var hand = createSvgElement('line');
|
||||
hand.setAttribute('x1', 0);
|
||||
hand.setAttribute('y1', 0);
|
||||
var bg = createSvgElement('circle');
|
||||
bg.setAttribute('class', 'clockpicker-canvas-bg');
|
||||
bg.setAttribute('r', tickRadius);
|
||||
var fg = createSvgElement('circle');
|
||||
fg.setAttribute('class', 'clockpicker-canvas-fg');
|
||||
fg.setAttribute('r', 5);
|
||||
g.appendChild(hand);
|
||||
g.appendChild(bg);
|
||||
g.appendChild(fg);
|
||||
g.appendChild(bearing);
|
||||
svg.appendChild(g);
|
||||
canvas.append(svg);
|
||||
|
||||
this.hand = hand;
|
||||
this.bg = bg;
|
||||
this.fg = fg;
|
||||
this.bearing = bearing;
|
||||
this.g = g;
|
||||
this.canvas = canvas;
|
||||
}
|
||||
|
||||
raiseCallback(this.options.init);
|
||||
}
|
||||
|
||||
function raiseCallback(callbackFunction) {
|
||||
if(callbackFunction && typeof callbackFunction === "function")
|
||||
callbackFunction();
|
||||
}
|
||||
|
||||
// Default options
|
||||
ClockPicker.DEFAULTS = {
|
||||
'default': '', // default time, 'now' or '13:14' e.g.
|
||||
fromnow: 0, // set default time to * milliseconds from now (using with default = 'now')
|
||||
donetext: 'Done', // done button text
|
||||
autoclose: false, // auto close when minute is selected
|
||||
ampmclickable: false, // set am/pm button on itself
|
||||
darktheme: false, // set to dark theme
|
||||
twelvehour: true, // change to 12 hour AM/PM clock from 24 hour
|
||||
vibrate: true // vibrate the device when dragging clock hand
|
||||
};
|
||||
|
||||
// Show or hide popover
|
||||
ClockPicker.prototype.toggle = function() {
|
||||
this[this.isShown ? 'hide' : 'show']();
|
||||
};
|
||||
|
||||
// Set popover position
|
||||
ClockPicker.prototype.locate = function() {
|
||||
var element = this.element,
|
||||
popover = this.popover,
|
||||
offset = element.offset(),
|
||||
width = element.outerWidth(),
|
||||
height = element.outerHeight(),
|
||||
align = this.options.align,
|
||||
self = this;
|
||||
|
||||
popover.show();
|
||||
};
|
||||
|
||||
// Show popover
|
||||
ClockPicker.prototype.show = function(e){
|
||||
// Not show again
|
||||
if (this.isShown) {
|
||||
return;
|
||||
}
|
||||
raiseCallback(this.options.beforeShow);
|
||||
$(':input').each(function() {
|
||||
$(this).attr('tabindex', -1);
|
||||
})
|
||||
var self = this;
|
||||
// Initialize
|
||||
this.input.blur();
|
||||
this.popover.addClass('picker--opened');
|
||||
this.input.addClass('picker__input picker__input--active');
|
||||
$(document.body).css('overflow', 'hidden');
|
||||
if (!this.isAppended) {
|
||||
// Append popover to body
|
||||
this.popover.insertAfter(this.input);
|
||||
if(this.options.twelvehour) {
|
||||
this.amOrPm = 'PM';
|
||||
if(!this.options.ampmclickable) {
|
||||
this.amPmBlock.children('.am-button').removeClass('active');
|
||||
this.amPmBlock.children('.pm-button').addClass('active');
|
||||
this.spanAmPm.empty().append('PM');
|
||||
}
|
||||
else {
|
||||
this.spanAmPm.children('#click-pm').addClass("text-primary");
|
||||
this.spanAmPm.children('#click-am').removeClass("text-primary");
|
||||
}
|
||||
}
|
||||
// Reset position when resize
|
||||
$win.on('resize.clockpicker' + this.id, function() {
|
||||
if (self.isShown) {
|
||||
self.locate();
|
||||
}
|
||||
});
|
||||
this.isAppended = true;
|
||||
}
|
||||
// Get the time
|
||||
var value = ((this.input.prop('value') || this.options['default'] || '') + '').split(':');
|
||||
if(this.options.twelvehour && !(typeof value[1] === 'undefined')) {
|
||||
value[1] = value[1].replace("AM", "").replace("PM", "");
|
||||
}
|
||||
if (value[0] === 'now') {
|
||||
var now = new Date(+ new Date() + this.options.fromnow);
|
||||
value = [
|
||||
now.getHours(),
|
||||
now.getMinutes()
|
||||
];
|
||||
}
|
||||
this.hours = + value[0] || 0;
|
||||
this.minutes = + value[1] || 0;
|
||||
this.spanHours.html(leadingZero(this.hours));
|
||||
this.spanMinutes.html(leadingZero(this.minutes));
|
||||
// Toggle to hours view
|
||||
this.toggleView('hours');
|
||||
// Set position
|
||||
this.locate();
|
||||
this.isShown = true;
|
||||
// Hide when clicking or tabbing on any element except the clock and input
|
||||
$doc.on('click.clockpicker.' + this.id + ' focusin.clockpicker.' + this.id, function(e) {
|
||||
var target = $(e.target);
|
||||
if (target.closest(self.popover.find('.picker__wrap')).length === 0 && target.closest(self.input).length === 0)
|
||||
self.hide();
|
||||
});
|
||||
// Hide when ESC is pressed
|
||||
$doc.on('keyup.clockpicker.' + this.id, function(e){
|
||||
if (e.keyCode === 27)
|
||||
self.hide();
|
||||
});
|
||||
raiseCallback(this.options.afterShow);
|
||||
};
|
||||
// Hide popover
|
||||
ClockPicker.prototype.hide = function() {
|
||||
raiseCallback(this.options.beforeHide);
|
||||
this.input.removeClass('picker__input picker__input--active');
|
||||
this.popover.removeClass('picker--opened');
|
||||
$(document.body).css('overflow', 'visible');
|
||||
this.isShown = false;
|
||||
$(':input').each(function(index) {
|
||||
$(this).attr('tabindex', index + 1);
|
||||
});
|
||||
// Unbinding events on document
|
||||
$doc.off('click.clockpicker.' + this.id + ' focusin.clockpicker.' + this.id);
|
||||
$doc.off('keyup.clockpicker.' + this.id);
|
||||
this.popover.hide();
|
||||
raiseCallback(this.options.afterHide);
|
||||
};
|
||||
// Toggle to hours or minutes view
|
||||
ClockPicker.prototype.toggleView = function(view, delay) {
|
||||
var raiseAfterHourSelect = false;
|
||||
if (view === 'minutes' && $(this.hoursView).css("visibility") === "visible") {
|
||||
raiseCallback(this.options.beforeHourSelect);
|
||||
raiseAfterHourSelect = true;
|
||||
}
|
||||
var isHours = view === 'hours',
|
||||
nextView = isHours ? this.hoursView : this.minutesView,
|
||||
hideView = isHours ? this.minutesView : this.hoursView;
|
||||
this.currentView = view;
|
||||
|
||||
this.spanHours.toggleClass('text-primary', isHours);
|
||||
this.spanMinutes.toggleClass('text-primary', ! isHours);
|
||||
|
||||
// Let's make transitions
|
||||
hideView.addClass('clockpicker-dial-out');
|
||||
nextView.css('visibility', 'visible').removeClass('clockpicker-dial-out');
|
||||
|
||||
// Reset clock hand
|
||||
this.resetClock(delay);
|
||||
|
||||
// After transitions ended
|
||||
clearTimeout(this.toggleViewTimer);
|
||||
this.toggleViewTimer = setTimeout(function() {
|
||||
hideView.css('visibility', 'hidden');
|
||||
}, duration);
|
||||
|
||||
if (raiseAfterHourSelect)
|
||||
raiseCallback(this.options.afterHourSelect);
|
||||
};
|
||||
|
||||
// Reset clock hand
|
||||
ClockPicker.prototype.resetClock = function(delay) {
|
||||
var view = this.currentView,
|
||||
value = this[view],
|
||||
isHours = view === 'hours',
|
||||
unit = Math.PI / (isHours ? 6 : 30),
|
||||
radian = value * unit,
|
||||
radius = isHours && value > 0 && value < 13 ? innerRadius : outerRadius,
|
||||
x = Math.sin(radian) * radius,
|
||||
y = - Math.cos(radian) * radius,
|
||||
self = this;
|
||||
|
||||
if(svgSupported && delay) {
|
||||
self.canvas.addClass('clockpicker-canvas-out');
|
||||
setTimeout(function(){
|
||||
self.canvas.removeClass('clockpicker-canvas-out');
|
||||
self.setHand(x, y);
|
||||
}, delay);
|
||||
} else
|
||||
this.setHand(x, y);
|
||||
};
|
||||
|
||||
// Set clock hand to (x, y)
|
||||
ClockPicker.prototype.setHand = function(x, y, roundBy5, dragging) {
|
||||
var radian = Math.atan2(x, - y),
|
||||
isHours = this.currentView === 'hours',
|
||||
unit = Math.PI / (isHours || roundBy5? 6 : 30),
|
||||
z = Math.sqrt(x * x + y * y),
|
||||
options = this.options,
|
||||
inner = isHours && z < (outerRadius + innerRadius) / 2,
|
||||
radius = inner ? innerRadius : outerRadius,
|
||||
value;
|
||||
|
||||
if (options.twelvehour)
|
||||
radius = outerRadius;
|
||||
|
||||
// Radian should in range [0, 2PI]
|
||||
if (radian < 0)
|
||||
radian = Math.PI * 2 + radian;
|
||||
|
||||
// Get the round value
|
||||
value = Math.round(radian / unit);
|
||||
|
||||
// Get the round radian
|
||||
radian = value * unit;
|
||||
|
||||
// Correct the hours or minutes
|
||||
if(options.twelvehour) {
|
||||
if(isHours) {
|
||||
if(value === 0)
|
||||
value = 12;
|
||||
} else {
|
||||
if(roundBy5)
|
||||
value *= 5;
|
||||
if(value === 60)
|
||||
value = 0;
|
||||
}
|
||||
} else {
|
||||
if(isHours) {
|
||||
if(value === 12)
|
||||
value = 0;
|
||||
value = inner ? (value === 0 ? 12 : value) : value === 0 ? 0 : value + 12;
|
||||
} else {
|
||||
if(roundBy5)
|
||||
value *= 5;
|
||||
if(value === 60)
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
if (isHours)
|
||||
this.fg.setAttribute('class', 'clockpicker-canvas-fg');
|
||||
else {
|
||||
if(value % 5 == 0)
|
||||
this.fg.setAttribute('class', 'clockpicker-canvas-fg');
|
||||
else
|
||||
this.fg.setAttribute('class', 'clockpicker-canvas-fg active');
|
||||
}
|
||||
|
||||
// Once hours or minutes changed, vibrate the device
|
||||
if (this[this.currentView] !== value)
|
||||
if (vibrate && this.options.vibrate)
|
||||
// Do not vibrate too frequently
|
||||
if (! this.vibrateTimer) {
|
||||
navigator[vibrate](10);
|
||||
this.vibrateTimer = setTimeout($.proxy(function(){
|
||||
this.vibrateTimer = null;
|
||||
}, this), 100);
|
||||
}
|
||||
|
||||
this[this.currentView] = value;
|
||||
this[isHours ? 'spanHours' : 'spanMinutes'].html(leadingZero(value));
|
||||
|
||||
// If svg is not supported, just add an active class to the tick
|
||||
if (! svgSupported) {
|
||||
this[isHours ? 'hoursView' : 'minutesView'].find('.clockpicker-tick').each(function(){
|
||||
var tick = $(this);
|
||||
tick.toggleClass('active', value === + tick.html());
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Place clock hand at the top when dragging
|
||||
if (dragging || (! isHours && value % 5)) {
|
||||
this.g.insertBefore(this.hand, this.bearing);
|
||||
this.g.insertBefore(this.bg, this.fg);
|
||||
this.bg.setAttribute('class', 'clockpicker-canvas-bg clockpicker-canvas-bg-trans');
|
||||
} else {
|
||||
// Or place it at the bottom
|
||||
this.g.insertBefore(this.hand, this.bg);
|
||||
this.g.insertBefore(this.fg, this.bg);
|
||||
this.bg.setAttribute('class', 'clockpicker-canvas-bg');
|
||||
}
|
||||
|
||||
// Set clock hand and others' position
|
||||
var cx1 = Math.sin(radian) * (radius - tickRadius),
|
||||
cy1 = - Math.cos(radian) * (radius - tickRadius),
|
||||
cx2 = Math.sin(radian) * radius,
|
||||
cy2 = - Math.cos(radian) * radius;
|
||||
this.hand.setAttribute('x2', cx1);
|
||||
this.hand.setAttribute('y2', cy1);
|
||||
this.bg.setAttribute('cx', cx2);
|
||||
this.bg.setAttribute('cy', cy2);
|
||||
this.fg.setAttribute('cx', cx2);
|
||||
this.fg.setAttribute('cy', cy2);
|
||||
};
|
||||
|
||||
// Hours and minutes are selected
|
||||
ClockPicker.prototype.done = function() {
|
||||
raiseCallback(this.options.beforeDone);
|
||||
this.hide();
|
||||
this.label.addClass('active');
|
||||
|
||||
var last = this.input.prop('value'),
|
||||
value = leadingZero(this.hours) + ':' + leadingZero(this.minutes);
|
||||
if (this.options.twelvehour)
|
||||
value = value + this.amOrPm;
|
||||
|
||||
this.input.prop('value', value);
|
||||
if(value !== last) {
|
||||
this.input.triggerHandler('change');
|
||||
if(!this.isInput)
|
||||
this.element.trigger('change');
|
||||
}
|
||||
|
||||
if(this.options.autoclose)
|
||||
this.input.trigger('blur');
|
||||
|
||||
raiseCallback(this.options.afterDone);
|
||||
};
|
||||
|
||||
// Remove clockpicker from input
|
||||
ClockPicker.prototype.remove = function() {
|
||||
this.element.removeData('clockpicker');
|
||||
this.input.off('focus.clockpicker click.clockpicker');
|
||||
if (this.isShown)
|
||||
this.hide();
|
||||
if (this.isAppended) {
|
||||
$win.off('resize.clockpicker' + this.id);
|
||||
this.popover.remove();
|
||||
}
|
||||
};
|
||||
|
||||
// Extends $.fn.clockpicker
|
||||
$.fn.pickatime = function(option){
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this.each(function(){
|
||||
var $this = $(this),
|
||||
data = $this.data('clockpicker');
|
||||
if (!data) {
|
||||
var options = $.extend({}, ClockPicker.DEFAULTS, $this.data(), typeof option == 'object' && option);
|
||||
$this.data('clockpicker', new ClockPicker($this, options));
|
||||
} else {
|
||||
// Manual operatsions. show, hide, remove, e.g.
|
||||
if (typeof data[option] === 'function')
|
||||
data[option].apply(data, args);
|
||||
}
|
||||
});
|
||||
};
|
||||
}());
|
||||
Executable
+1163
File diff suppressed because it is too large
Load Diff
Executable
+11
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
// Preloading script
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#preloader-markup').load('mdb-addons/preloader.html', function () {
|
||||
$(window).on('load', function () {
|
||||
$('#mdb-preloader').fadeOut('slow');
|
||||
});
|
||||
});
|
||||
});
|
||||
Executable
+132
@@ -0,0 +1,132 @@
|
||||
'use strict';
|
||||
|
||||
/** **************
|
||||
* Range Input *
|
||||
****************/
|
||||
(function ($) {
|
||||
|
||||
var range_wrapper = '.range-field';
|
||||
var range_type = 'input[type=range]';
|
||||
var thumb_html = '<span class="thumb"><span class="value"></span></span>';
|
||||
var range_mousedown = false;
|
||||
var left = void 0;
|
||||
|
||||
var add_thumb = function add_thumb() {
|
||||
var $thumb = $(thumb_html);
|
||||
$(range_type).after($thumb);
|
||||
};
|
||||
|
||||
// Add thumbs;
|
||||
$(range_type).each(add_thumb);
|
||||
|
||||
$(document).on('change', range_type, function () {
|
||||
var $thumb = $(this);
|
||||
var $thumb_value = $thumb.siblings('.thumb').find('.value');
|
||||
$thumb_value.html($thumb.val());
|
||||
});
|
||||
|
||||
$(document).on('input mousedown touchstart', range_type, function (e) {
|
||||
var $this = $(this);
|
||||
var $thumb = $this.siblings('.thumb');
|
||||
var width = $this.outerWidth();
|
||||
var noThumb = !$thumb.length;
|
||||
// If thumb indicator does not exist yet, create it
|
||||
if (noThumb) {
|
||||
add_thumb();
|
||||
}
|
||||
|
||||
// Set indicator value
|
||||
$thumb.find('.value').html($this.val());
|
||||
|
||||
range_mousedown = true;
|
||||
$this.addClass('active');
|
||||
|
||||
if (!$thumb.hasClass('active')) {
|
||||
$thumb.velocity({
|
||||
height: '30px',
|
||||
width: '30px',
|
||||
top: '-20px',
|
||||
marginLeft: '-15px'
|
||||
}, {
|
||||
duration: 300,
|
||||
easing: 'easeOutExpo'
|
||||
});
|
||||
}
|
||||
|
||||
if (e.type !== 'input') {
|
||||
var isMobile = e.pageX === undefined || e.pageX === null;
|
||||
if (isMobile) {
|
||||
left = e.originalEvent.touches[0].pageX - $(this).offset().left;
|
||||
} else {
|
||||
left = e.pageX - $(this).offset().left;
|
||||
}
|
||||
|
||||
if (left < 0) {
|
||||
left = 0;
|
||||
} else if (left > width) {
|
||||
left = width;
|
||||
}
|
||||
$thumb.addClass('active').css('left', left);
|
||||
}
|
||||
|
||||
$thumb.find('.value').html($this.val());
|
||||
});
|
||||
|
||||
$(document).on('mouseup touchend', range_wrapper, function () {
|
||||
range_mousedown = false;
|
||||
$(this).removeClass('active');
|
||||
});
|
||||
|
||||
$(document).on('mousemove touchmove', range_wrapper, function (e) {
|
||||
var $thumb = $(this).children('.thumb');
|
||||
var left = void 0;
|
||||
|
||||
if (range_mousedown) {
|
||||
if (!$thumb.hasClass('active')) {
|
||||
$thumb.velocity({
|
||||
height: '30px',
|
||||
width: '30px',
|
||||
top: '-20px',
|
||||
marginLeft: '-15px'
|
||||
}, {
|
||||
duration: 300,
|
||||
easing: 'easeOutExpo'
|
||||
});
|
||||
}
|
||||
var isMobile = e.pageX === undefined || e.pageX === null;
|
||||
if (isMobile) {
|
||||
left = e.originalEvent.touches[0].pageX - $(this).offset().left;
|
||||
} else {
|
||||
left = e.pageX - $(this).offset().left;
|
||||
}
|
||||
|
||||
var width = $(this).outerWidth();
|
||||
if (left < 0) {
|
||||
left = 0;
|
||||
} else if (left > width) {
|
||||
left = width;
|
||||
}
|
||||
|
||||
$thumb.addClass('active').css('left', left);
|
||||
$thumb.find('.value').html($thumb.siblings(range_type).val());
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('mouseout touchleave', range_wrapper, function () {
|
||||
if (!range_mousedown) {
|
||||
var $thumb = $(this).children('.thumb');
|
||||
|
||||
if ($thumb.hasClass('active')) {
|
||||
$thumb.velocity({
|
||||
height: '0',
|
||||
width: '0',
|
||||
top: '10px',
|
||||
marginLeft: '-6px'
|
||||
}, {
|
||||
duration: 100
|
||||
});
|
||||
}
|
||||
$thumb.removeClass('active');
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,6 @@
|
||||
/* ROTATING CARDS */
|
||||
$('.rotate-btn').on('click', function () {
|
||||
var cardId = $(this).attr('data-card');
|
||||
$('#' + cardId).toggleClass('flipped');
|
||||
|
||||
});
|
||||
Executable
+2
File diff suppressed because one or more lines are too long
@@ -0,0 +1,23 @@
|
||||
/* SCROLLING NAVBAR */
|
||||
//jQuery to collapse the navbar on scroll
|
||||
$(window).scroll(function () {
|
||||
if ($(".navbar").offset()) {
|
||||
if ($(".navbar").offset().top > 50) {
|
||||
$(".scrolling-navbar").addClass("top-nav-collapse");
|
||||
} else {
|
||||
$(".scrolling-navbar").removeClass("top-nav-collapse");
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//jQuery for page scrolling feature - requires jQuery Easing plugin
|
||||
$(function () {
|
||||
$('a.page-scroll').bind('click', function (event) {
|
||||
var $anchor = $(this);
|
||||
$('html, body').stop().animate({
|
||||
scrollTop: $($anchor.attr('href')).offset().top
|
||||
}, 1500, 'easeInOutExpo');
|
||||
event.preventDefault();
|
||||
});
|
||||
});
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
/* SCROLLING NAVBAR */
|
||||
var OFFSET_TOP = 50;
|
||||
|
||||
$(window).scroll(function () {
|
||||
if ($('.navbar').length) {
|
||||
if ($('.navbar').offset().top > OFFSET_TOP) {
|
||||
$('.scrolling-navbar').addClass('top-nav-collapse');
|
||||
} else {
|
||||
$('.scrolling-navbar').removeClass('top-nav-collapse');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,344 @@
|
||||
(function ($) {
|
||||
|
||||
var methods = {
|
||||
init : function(options) {
|
||||
var defaults = {
|
||||
menuWidth: 240,
|
||||
edge: 'left',
|
||||
closeOnClick: false
|
||||
};
|
||||
options = $.extend(defaults, options);
|
||||
|
||||
$(this).each(function(){
|
||||
var $this = $(this);
|
||||
var menu_id = $("#"+ $this.attr('data-activates'));
|
||||
|
||||
// Set to width
|
||||
if (options.menuWidth != 240) {
|
||||
menu_id.css('width', options.menuWidth);
|
||||
}
|
||||
|
||||
// Add Touch Area
|
||||
var dragTarget = $('<div class="drag-target"></div>');
|
||||
$('body').append(dragTarget);
|
||||
|
||||
if (options.edge == 'left') {
|
||||
menu_id.css('transform', 'translateX(-100%)');
|
||||
dragTarget.css({'left': 0}); // Add Touch Area
|
||||
}
|
||||
else {
|
||||
menu_id.addClass('right-aligned') // Change text-alignment to right
|
||||
.css('transform', 'translateX(100%)');
|
||||
dragTarget.css({'right': 0}); // Add Touch Area
|
||||
}
|
||||
|
||||
// If fixed sidenav, bring menu out
|
||||
if (menu_id.hasClass('fixed')) {
|
||||
if (window.innerWidth > 1440) {
|
||||
menu_id.css('transform', 'translateX(0)');
|
||||
}
|
||||
}
|
||||
|
||||
// Window resize to reset on large screens fixed
|
||||
if (menu_id.hasClass('fixed')) {
|
||||
$(window).resize( function() {
|
||||
if (window.innerWidth > 1440) {
|
||||
// Close menu if window is resized bigger than 992 and user has fixed sidenav
|
||||
if ($('#sidenav-overlay').length != 0 && menuOut) {
|
||||
removeMenu(true);
|
||||
}
|
||||
else {
|
||||
// menu_id.removeAttr('style');
|
||||
menu_id.css('transform', 'translateX(0%)');
|
||||
// menu_id.css('width', options.menuWidth);
|
||||
}
|
||||
}
|
||||
else if (menuOut === false){
|
||||
if (options.edge === 'left') {
|
||||
menu_id.css('transform', 'translateX(-100%)');
|
||||
} else {
|
||||
menu_id.css('transform', 'translateX(100%)');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// if closeOnClick, then add close event for all a tags in side sideNav
|
||||
if (options.closeOnClick === true) {
|
||||
menu_id.on("click.itemclick", "a:not(.collapsible-header)", function(){
|
||||
removeMenu();
|
||||
});
|
||||
}
|
||||
|
||||
function removeMenu(restoreNav) {
|
||||
panning = false;
|
||||
menuOut = false;
|
||||
// Reenable scrolling
|
||||
$('body').css({
|
||||
overflow: '',
|
||||
width: ''
|
||||
});
|
||||
|
||||
$('#sidenav-overlay').velocity({opacity: 0}, {duration: 200,
|
||||
queue: false, easing: 'easeOutQuad',
|
||||
complete: function() {
|
||||
$(this).remove();
|
||||
} });
|
||||
if (options.edge === 'left') {
|
||||
// Reset phantom div
|
||||
dragTarget.css({width: '', right: '', left: '0'});
|
||||
menu_id.velocity(
|
||||
{'translateX': '-100%'},
|
||||
{ duration: 200,
|
||||
queue: false,
|
||||
easing: 'easeOutCubic',
|
||||
complete: function() {
|
||||
if (restoreNav === true) {
|
||||
// Restore Fixed sidenav
|
||||
menu_id.removeAttr('style');
|
||||
menu_id.css('width', options.menuWidth);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Reset phantom div
|
||||
dragTarget.css({width: '', right: '0', left: ''});
|
||||
menu_id.velocity(
|
||||
{'translateX': '100%'},
|
||||
{ duration: 200,
|
||||
queue: false,
|
||||
easing: 'easeOutCubic',
|
||||
complete: function() {
|
||||
if (restoreNav === true) {
|
||||
// Restore Fixed sidenav
|
||||
menu_id.removeAttr('style');
|
||||
menu_id.css('width', options.menuWidth);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Touch Event
|
||||
var panning = false;
|
||||
var menuOut = false;
|
||||
|
||||
dragTarget.on('click', function(){
|
||||
removeMenu();
|
||||
});
|
||||
|
||||
dragTarget.hammer({
|
||||
prevent_default: false
|
||||
}).bind('pan', function(e) {
|
||||
|
||||
if (e.gesture.pointerType == "touch") {
|
||||
|
||||
var direction = e.gesture.direction;
|
||||
var x = e.gesture.center.x;
|
||||
var y = e.gesture.center.y;
|
||||
var velocityX = e.gesture.velocityX;
|
||||
|
||||
// Disable Scrolling
|
||||
var $body = $('body');
|
||||
var oldWidth = $body.innerWidth();
|
||||
$body.css('overflow', 'hidden');
|
||||
$body.width(oldWidth);
|
||||
|
||||
// If overlay does not exist, create one and if it is clicked, close menu
|
||||
if ($('#sidenav-overlay').length === 0) {
|
||||
var overlay = $('<div id="sidenav-overlay"></div>');
|
||||
overlay.css('opacity', 0).click( function(){
|
||||
removeMenu();
|
||||
});
|
||||
$('body').append(overlay);
|
||||
}
|
||||
|
||||
// Keep within boundaries
|
||||
if (options.edge === 'left') {
|
||||
if (x > options.menuWidth) { x = options.menuWidth; }
|
||||
else if (x < 0) { x = 0; }
|
||||
}
|
||||
|
||||
if (options.edge === 'left') {
|
||||
// Left Direction
|
||||
if (x < (options.menuWidth / 2)) { menuOut = false; }
|
||||
// Right Direction
|
||||
else if (x >= (options.menuWidth / 2)) { menuOut = true; }
|
||||
menu_id.css('transform', 'translateX(' + (x - options.menuWidth) + 'px)');
|
||||
}
|
||||
else {
|
||||
// Left Direction
|
||||
if (x < (window.innerWidth - options.menuWidth / 2)) {
|
||||
menuOut = true;
|
||||
}
|
||||
// Right Direction
|
||||
else if (x >= (window.innerWidth - options.menuWidth / 2)) {
|
||||
menuOut = false;
|
||||
}
|
||||
var rightPos = (x - options.menuWidth / 2);
|
||||
if (rightPos < 0) {
|
||||
rightPos = 0;
|
||||
}
|
||||
|
||||
menu_id.css('transform', 'translateX(' + rightPos + 'px)');
|
||||
}
|
||||
|
||||
|
||||
// Percentage overlay
|
||||
var overlayPerc;
|
||||
if (options.edge === 'left') {
|
||||
overlayPerc = x / options.menuWidth;
|
||||
$('#sidenav-overlay').velocity({opacity: overlayPerc }, {duration: 10, queue: false, easing: 'easeOutQuad'});
|
||||
}
|
||||
else {
|
||||
overlayPerc = Math.abs((x - window.innerWidth) / options.menuWidth);
|
||||
$('#sidenav-overlay').velocity({opacity: overlayPerc }, {duration: 10, queue: false, easing: 'easeOutQuad'});
|
||||
}
|
||||
}
|
||||
|
||||
}).bind('panend', function(e) {
|
||||
|
||||
if (e.gesture.pointerType == "touch") {
|
||||
var velocityX = e.gesture.velocityX;
|
||||
var x = e.gesture.center.x;
|
||||
var leftPos = x - options.menuWidth;
|
||||
var rightPos = x - options.menuWidth / 2;
|
||||
if (leftPos > 0 ) {
|
||||
leftPos = 0;
|
||||
}
|
||||
if (rightPos < 0) {
|
||||
rightPos = 0;
|
||||
}
|
||||
panning = false;
|
||||
|
||||
if (options.edge === 'left') {
|
||||
// If velocityX <= 0.3 then the user is flinging the menu closed so ignore menuOut
|
||||
if ((menuOut && velocityX <= 0.3) || velocityX < -0.5) {
|
||||
if (leftPos != 0) {
|
||||
menu_id.velocity({'translateX': [0, leftPos]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
||||
}
|
||||
|
||||
// menu_id.css({'translateX': 0});
|
||||
$('#sidenav-overlay').velocity({opacity: 1 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
|
||||
dragTarget.css({width: '50%', right: 0, left: ''});
|
||||
}
|
||||
else if (!menuOut || velocityX > 0.3) {
|
||||
// Enable Scrolling
|
||||
$('body').css({
|
||||
overflow: '',
|
||||
width: ''
|
||||
});
|
||||
// Slide menu closed
|
||||
menu_id.velocity({'translateX': [-1 * options.menuWidth - 10, leftPos]}, {duration: 200, queue: false, easing: 'easeOutQuad'});
|
||||
$('#sidenav-overlay').velocity({opacity: 0 }, {duration: 200, queue: false, easing: 'easeOutQuad',
|
||||
complete: function () {
|
||||
$(this).remove();
|
||||
}});
|
||||
dragTarget.css({width: '10px', right: '', left: 0});
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((menuOut && velocityX >= -0.3) || velocityX > 0.5) {
|
||||
menu_id.velocity({'translateX': [0, rightPos]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
||||
$('#sidenav-overlay').velocity({opacity: 1 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
|
||||
dragTarget.css({width: '50%', right: '', left: 0});
|
||||
}
|
||||
else if (!menuOut || velocityX < -0.3) {
|
||||
// Enable Scrolling
|
||||
$('body').css({
|
||||
overflow: '',
|
||||
width: ''
|
||||
});
|
||||
|
||||
// Slide menu closed
|
||||
menu_id.velocity({'translateX': [options.menuWidth + 10, rightPos]}, {duration: 200, queue: false, easing: 'easeOutQuad'});
|
||||
$('#sidenav-overlay').velocity({opacity: 0 }, {duration: 200, queue: false, easing: 'easeOutQuad',
|
||||
complete: function () {
|
||||
$(this).remove();
|
||||
}});
|
||||
dragTarget.css({width: '10px', right: 0, left: ''});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
$this.click(function() {
|
||||
if (menuOut === true) {
|
||||
menuOut = false;
|
||||
panning = false;
|
||||
removeMenu();
|
||||
}
|
||||
else {
|
||||
|
||||
// Disable Scrolling
|
||||
var $body = $('body');
|
||||
var oldWidth = $body.innerWidth();
|
||||
$body.css('overflow', 'hidden');
|
||||
$body.width(oldWidth);
|
||||
|
||||
// Push current drag target on top of DOM tree
|
||||
$('body').append(dragTarget);
|
||||
|
||||
if (options.edge === 'left') {
|
||||
dragTarget.css({width: '50%', right: 0, left: ''});
|
||||
menu_id.velocity({'translateX': [0, -1 * options.menuWidth]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
||||
}
|
||||
else {
|
||||
dragTarget.css({width: '50%', right: '', left: 0});
|
||||
menu_id.velocity({'translateX': [0, options.menuWidth]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
||||
}
|
||||
|
||||
var overlay = $('<div id="sidenav-overlay"></div>');
|
||||
overlay.css('opacity', 0)
|
||||
.click(function(){
|
||||
menuOut = false;
|
||||
panning = false;
|
||||
removeMenu();
|
||||
overlay.velocity({opacity: 0}, {duration: 300, queue: false, easing: 'easeOutQuad',
|
||||
complete: function() {
|
||||
$(this).remove();
|
||||
} });
|
||||
|
||||
});
|
||||
$('body').append(overlay);
|
||||
overlay.velocity({opacity: 1}, {duration: 300, queue: false, easing: 'easeOutQuad',
|
||||
complete: function () {
|
||||
menuOut = true;
|
||||
panning = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
show : function() {
|
||||
this.trigger('click');
|
||||
},
|
||||
hide : function() {
|
||||
$('#sidenav-overlay').trigger('click');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$.fn.sideNav = function(methodOrOptions) {
|
||||
if ( methods[methodOrOptions] ) {
|
||||
return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 ));
|
||||
} else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) {
|
||||
// Default to "init"
|
||||
return methods.init.apply( this, arguments );
|
||||
} else {
|
||||
$.error( 'Method ' + methodOrOptions + ' does not exist on jQuery.sideNav' );
|
||||
}
|
||||
}; // Plugin end
|
||||
}( jQuery ));
|
||||
@@ -0,0 +1,344 @@
|
||||
(function ($) {
|
||||
|
||||
var methods = {
|
||||
init : function(options) {
|
||||
var defaults = {
|
||||
menuWidth: 240,
|
||||
edge: 'left',
|
||||
closeOnClick: false
|
||||
};
|
||||
options = $.extend(defaults, options);
|
||||
|
||||
$(this).each(function(){
|
||||
var $this = $(this);
|
||||
var menu_id = $("#"+ $this.attr('data-activates'));
|
||||
|
||||
// Set to width
|
||||
if (options.menuWidth != 240) {
|
||||
menu_id.css('width', options.menuWidth);
|
||||
}
|
||||
|
||||
// Add Touch Area
|
||||
var dragTarget = $('<div class="drag-target"></div>');
|
||||
$('body').append(dragTarget);
|
||||
|
||||
if (options.edge == 'left') {
|
||||
menu_id.css('transform', 'translateX(-100%)');
|
||||
dragTarget.css({'left': 0}); // Add Touch Area
|
||||
}
|
||||
else {
|
||||
menu_id.addClass('right-aligned') // Change text-alignment to right
|
||||
.css('transform', 'translateX(100%)');
|
||||
dragTarget.css({'right': 0}); // Add Touch Area
|
||||
}
|
||||
|
||||
// If fixed sidenav, bring menu out
|
||||
if (menu_id.hasClass('fixed')) {
|
||||
if (window.innerWidth > 1440) {
|
||||
menu_id.css('transform', 'translateX(0)');
|
||||
}
|
||||
}
|
||||
|
||||
// Window resize to reset on large screens fixed
|
||||
if (menu_id.hasClass('fixed')) {
|
||||
$(window).resize( function() {
|
||||
if (window.innerWidth > 1440) {
|
||||
// Close menu if window is resized bigger than 992 and user has fixed sidenav
|
||||
if ($('#sidenav-overlay').length != 0 && menuOut) {
|
||||
removeMenu(true);
|
||||
}
|
||||
else {
|
||||
// menu_id.removeAttr('style');
|
||||
menu_id.css('transform', 'translateX(0%)');
|
||||
// menu_id.css('width', options.menuWidth);
|
||||
}
|
||||
}
|
||||
else if (menuOut === false){
|
||||
if (options.edge === 'left') {
|
||||
menu_id.css('transform', 'translateX(-100%)');
|
||||
} else {
|
||||
menu_id.css('transform', 'translateX(100%)');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// if closeOnClick, then add close event for all a tags in side sideNav
|
||||
if (options.closeOnClick === true) {
|
||||
menu_id.on("click.itemclick", "a:not(.collapsible-header)", function(){
|
||||
removeMenu();
|
||||
});
|
||||
}
|
||||
|
||||
function removeMenu(restoreNav) {
|
||||
panning = false;
|
||||
menuOut = false;
|
||||
// Reenable scrolling
|
||||
$('body').css({
|
||||
overflow: '',
|
||||
width: ''
|
||||
});
|
||||
|
||||
$('#sidenav-overlay').velocity({opacity: 0}, {duration: 200,
|
||||
queue: false, easing: 'easeOutQuad',
|
||||
complete: function() {
|
||||
$(this).remove();
|
||||
} });
|
||||
if (options.edge === 'left') {
|
||||
// Reset phantom div
|
||||
dragTarget.css({width: '', right: '', left: '0'});
|
||||
menu_id.velocity(
|
||||
{'translateX': '-100%'},
|
||||
{ duration: 200,
|
||||
queue: false,
|
||||
easing: 'easeOutCubic',
|
||||
complete: function() {
|
||||
if (restoreNav === true) {
|
||||
// Restore Fixed sidenav
|
||||
menu_id.removeAttr('style');
|
||||
menu_id.css('width', options.menuWidth);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Reset phantom div
|
||||
dragTarget.css({width: '', right: '0', left: ''});
|
||||
menu_id.velocity(
|
||||
{'translateX': '100%'},
|
||||
{ duration: 200,
|
||||
queue: false,
|
||||
easing: 'easeOutCubic',
|
||||
complete: function() {
|
||||
if (restoreNav === true) {
|
||||
// Restore Fixed sidenav
|
||||
menu_id.removeAttr('style');
|
||||
menu_id.css('width', options.menuWidth);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Touch Event
|
||||
var panning = false;
|
||||
var menuOut = false;
|
||||
|
||||
dragTarget.on('click', function(){
|
||||
removeMenu();
|
||||
});
|
||||
|
||||
dragTarget.hammer({
|
||||
prevent_default: false
|
||||
}).bind('pan', function(e) {
|
||||
|
||||
if (e.gesture.pointerType == "touch") {
|
||||
|
||||
var direction = e.gesture.direction;
|
||||
var x = e.gesture.center.x;
|
||||
var y = e.gesture.center.y;
|
||||
var velocityX = e.gesture.velocityX;
|
||||
|
||||
// Disable Scrolling
|
||||
var $body = $('body');
|
||||
var oldWidth = $body.innerWidth();
|
||||
$body.css('overflow', 'hidden');
|
||||
$body.width(oldWidth);
|
||||
|
||||
// If overlay does not exist, create one and if it is clicked, close menu
|
||||
if ($('#sidenav-overlay').length === 0) {
|
||||
var overlay = $('<div id="sidenav-overlay"></div>');
|
||||
overlay.css('opacity', 0).click( function(){
|
||||
removeMenu();
|
||||
});
|
||||
$('body').append(overlay);
|
||||
}
|
||||
|
||||
// Keep within boundaries
|
||||
if (options.edge === 'left') {
|
||||
if (x > options.menuWidth) { x = options.menuWidth; }
|
||||
else if (x < 0) { x = 0; }
|
||||
}
|
||||
|
||||
if (options.edge === 'left') {
|
||||
// Left Direction
|
||||
if (x < (options.menuWidth / 2)) { menuOut = false; }
|
||||
// Right Direction
|
||||
else if (x >= (options.menuWidth / 2)) { menuOut = true; }
|
||||
menu_id.css('transform', 'translateX(' + (x - options.menuWidth) + 'px)');
|
||||
}
|
||||
else {
|
||||
// Left Direction
|
||||
if (x < (window.innerWidth - options.menuWidth / 2)) {
|
||||
menuOut = true;
|
||||
}
|
||||
// Right Direction
|
||||
else if (x >= (window.innerWidth - options.menuWidth / 2)) {
|
||||
menuOut = false;
|
||||
}
|
||||
var rightPos = (x - options.menuWidth / 2);
|
||||
if (rightPos < 0) {
|
||||
rightPos = 0;
|
||||
}
|
||||
|
||||
menu_id.css('transform', 'translateX(' + rightPos + 'px)');
|
||||
}
|
||||
|
||||
|
||||
// Percentage overlay
|
||||
var overlayPerc;
|
||||
if (options.edge === 'left') {
|
||||
overlayPerc = x / options.menuWidth;
|
||||
$('#sidenav-overlay').velocity({opacity: overlayPerc }, {duration: 10, queue: false, easing: 'easeOutQuad'});
|
||||
}
|
||||
else {
|
||||
overlayPerc = Math.abs((x - window.innerWidth) / options.menuWidth);
|
||||
$('#sidenav-overlay').velocity({opacity: overlayPerc }, {duration: 10, queue: false, easing: 'easeOutQuad'});
|
||||
}
|
||||
}
|
||||
|
||||
}).bind('panend', function(e) {
|
||||
|
||||
if (e.gesture.pointerType == "touch") {
|
||||
var velocityX = e.gesture.velocityX;
|
||||
var x = e.gesture.center.x;
|
||||
var leftPos = x - options.menuWidth;
|
||||
var rightPos = x - options.menuWidth / 2;
|
||||
if (leftPos > 0 ) {
|
||||
leftPos = 0;
|
||||
}
|
||||
if (rightPos < 0) {
|
||||
rightPos = 0;
|
||||
}
|
||||
panning = false;
|
||||
|
||||
if (options.edge === 'left') {
|
||||
// If velocityX <= 0.3 then the user is flinging the menu closed so ignore menuOut
|
||||
if ((menuOut && velocityX <= 0.3) || velocityX < -0.5) {
|
||||
if (leftPos != 0) {
|
||||
menu_id.velocity({'translateX': [0, leftPos]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
||||
}
|
||||
|
||||
// menu_id.css({'translateX': 0});
|
||||
$('#sidenav-overlay').velocity({opacity: 1 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
|
||||
dragTarget.css({width: '50%', right: 0, left: ''});
|
||||
}
|
||||
else if (!menuOut || velocityX > 0.3) {
|
||||
// Enable Scrolling
|
||||
$('body').css({
|
||||
overflow: '',
|
||||
width: ''
|
||||
});
|
||||
// Slide menu closed
|
||||
menu_id.velocity({'translateX': [-1 * options.menuWidth - 10, leftPos]}, {duration: 200, queue: false, easing: 'easeOutQuad'});
|
||||
$('#sidenav-overlay').velocity({opacity: 0 }, {duration: 200, queue: false, easing: 'easeOutQuad',
|
||||
complete: function () {
|
||||
$(this).remove();
|
||||
}});
|
||||
dragTarget.css({width: '10px', right: '', left: 0});
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((menuOut && velocityX >= -0.3) || velocityX > 0.5) {
|
||||
menu_id.velocity({'translateX': [0, rightPos]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
||||
$('#sidenav-overlay').velocity({opacity: 1 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
|
||||
dragTarget.css({width: '50%', right: '', left: 0});
|
||||
}
|
||||
else if (!menuOut || velocityX < -0.3) {
|
||||
// Enable Scrolling
|
||||
$('body').css({
|
||||
overflow: '',
|
||||
width: ''
|
||||
});
|
||||
|
||||
// Slide menu closed
|
||||
menu_id.velocity({'translateX': [options.menuWidth + 10, rightPos]}, {duration: 200, queue: false, easing: 'easeOutQuad'});
|
||||
$('#sidenav-overlay').velocity({opacity: 0 }, {duration: 200, queue: false, easing: 'easeOutQuad',
|
||||
complete: function () {
|
||||
$(this).remove();
|
||||
}});
|
||||
dragTarget.css({width: '10px', right: 0, left: ''});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
$this.click(function() {
|
||||
if (menuOut === true) {
|
||||
menuOut = false;
|
||||
panning = false;
|
||||
removeMenu();
|
||||
}
|
||||
else {
|
||||
|
||||
// Disable Scrolling
|
||||
var $body = $('body');
|
||||
var oldWidth = $body.innerWidth();
|
||||
$body.css('overflow', 'hidden');
|
||||
$body.width(oldWidth);
|
||||
|
||||
// Push current drag target on top of DOM tree
|
||||
$('body').append(dragTarget);
|
||||
|
||||
if (options.edge === 'left') {
|
||||
dragTarget.css({width: '50%', right: 0, left: ''});
|
||||
menu_id.velocity({'translateX': [0, -1 * options.menuWidth]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
||||
}
|
||||
else {
|
||||
dragTarget.css({width: '50%', right: '', left: 0});
|
||||
menu_id.velocity({'translateX': [0, options.menuWidth]}, {duration: 300, queue: false, easing: 'easeOutQuad'});
|
||||
}
|
||||
|
||||
var overlay = $('<div id="sidenav-overlay"></div>');
|
||||
overlay.css('opacity', 0)
|
||||
.click(function(){
|
||||
menuOut = false;
|
||||
panning = false;
|
||||
removeMenu();
|
||||
overlay.velocity({opacity: 0}, {duration: 300, queue: false, easing: 'easeOutQuad',
|
||||
complete: function() {
|
||||
$(this).remove();
|
||||
} });
|
||||
|
||||
});
|
||||
$('body').append(overlay);
|
||||
overlay.velocity({opacity: 1}, {duration: 300, queue: false, easing: 'easeOutQuad',
|
||||
complete: function () {
|
||||
menuOut = true;
|
||||
panning = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
show : function() {
|
||||
this.trigger('click');
|
||||
},
|
||||
hide : function() {
|
||||
$('#sidenav-overlay').trigger('click');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$.fn.sideNav = function(methodOrOptions) {
|
||||
if ( methods[methodOrOptions] ) {
|
||||
return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 ));
|
||||
} else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) {
|
||||
// Default to "init"
|
||||
return methods.init.apply( this, arguments );
|
||||
} else {
|
||||
$.error( 'Method ' + methodOrOptions + ' does not exist on jQuery.sideNav' );
|
||||
}
|
||||
}; // Plugin end
|
||||
}( jQuery ));
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
||||
|
||||
// SMOOTH SCROLL
|
||||
var SMOOTH_SCROLL_DURATION = 700;
|
||||
|
||||
$('.smooth-scroll').on('click', 'a', function (event) {
|
||||
event.preventDefault();
|
||||
var elAttr = $(this).attr('href');
|
||||
var offset = $(this).attr('data-offset') ? $(this).attr('data-offset') : 0;
|
||||
var setHash = $(this).closest('ul').attr('data-allow-hashes');
|
||||
$('body,html').animate({
|
||||
scrollTop: $(elAttr).offset().top - offset
|
||||
}, SMOOTH_SCROLL_DURATION);
|
||||
if ((typeof setHash === 'undefined' ? 'undefined' : _typeof(setHash)) !== (typeof undefined === 'undefined' ? 'undefined' : _typeof(undefined)) && setHash !== false) {
|
||||
history.replaceState(null, null, elAttr);
|
||||
}
|
||||
});
|
||||
Executable
+416
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* Toastr
|
||||
* Copyright 2012-2015
|
||||
* Authors: John Papa, Hans Fjällemark, and Tim Ferrell.
|
||||
* All Rights Reserved.
|
||||
* Use, reproduction, distribution, and modification of this code is subject to the terms and
|
||||
* conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* ARIA Support: Greta Krafsig
|
||||
*
|
||||
* Project: https://github.com/CodeSeven/toastr
|
||||
*/
|
||||
/* global define */
|
||||
; (function (define) {
|
||||
define(['jquery'], function ($) {
|
||||
return (function () {
|
||||
var $container;
|
||||
var listener;
|
||||
var toastId = 0;
|
||||
var toastType = {
|
||||
error: 'error',
|
||||
info: 'info',
|
||||
success: 'success',
|
||||
warning: 'warning'
|
||||
};
|
||||
|
||||
var toastr = {
|
||||
clear: clear,
|
||||
remove: remove,
|
||||
error: error,
|
||||
getContainer: getContainer,
|
||||
info: info,
|
||||
options: {},
|
||||
subscribe: subscribe,
|
||||
success: success,
|
||||
version: '2.1.1',
|
||||
warning: warning
|
||||
};
|
||||
|
||||
var previousToast;
|
||||
|
||||
return toastr;
|
||||
|
||||
////////////////
|
||||
|
||||
function error(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.error,
|
||||
iconClass: getOptions().iconClasses.error,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function getContainer(options, create) {
|
||||
if (!options) { options = getOptions(); }
|
||||
$container = $('#' + options.containerId + '[position = ' + options.positionClass + ']');
|
||||
if ($container.length) {
|
||||
return $container;
|
||||
}
|
||||
if (create) {
|
||||
$container = createContainer(options);
|
||||
}
|
||||
return $container;
|
||||
}
|
||||
|
||||
function info(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.info,
|
||||
iconClass: getOptions().iconClasses.info,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function subscribe(callback) {
|
||||
listener = callback;
|
||||
}
|
||||
|
||||
function success(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.success,
|
||||
iconClass: getOptions().iconClasses.success,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function warning(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.warning,
|
||||
iconClass: getOptions().iconClasses.warning,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function clear($toastElement, clearOptions) {
|
||||
var options = getOptions();
|
||||
if (!$container) { getContainer(options); }
|
||||
if (!clearToast($toastElement, options, clearOptions)) {
|
||||
clearContainer(options);
|
||||
}
|
||||
}
|
||||
|
||||
function remove($toastElement) {
|
||||
var options = getOptions();
|
||||
if (!$container) { getContainer(options); }
|
||||
if ($toastElement && $(':focus', $toastElement).length === 0) {
|
||||
removeToast($toastElement);
|
||||
return;
|
||||
}
|
||||
if ($container.children().length) {
|
||||
$container.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// internal functions
|
||||
|
||||
function clearContainer (options) {
|
||||
var toastsToClear = $container.children();
|
||||
for (var i = toastsToClear.length - 1; i >= 0; i--) {
|
||||
clearToast($(toastsToClear[i]), options);
|
||||
}
|
||||
}
|
||||
|
||||
function clearToast ($toastElement, options, clearOptions) {
|
||||
var force = clearOptions && clearOptions.force ? clearOptions.force : false;
|
||||
if ($toastElement && (force || $(':focus', $toastElement).length === 0)) {
|
||||
$toastElement[options.hideMethod]({
|
||||
duration: options.hideDuration,
|
||||
easing: options.hideEasing,
|
||||
complete: function () { removeToast($toastElement); }
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function createContainer(options) {
|
||||
$container = $('<div/>')
|
||||
.attr('id', options.containerId)
|
||||
.attr('position', options.positionClass)
|
||||
.addClass(options.positionClass)
|
||||
.attr('aria-live', 'polite')
|
||||
.attr('role', 'alert');
|
||||
|
||||
$container.appendTo($(options.target));
|
||||
return $container;
|
||||
}
|
||||
|
||||
function getDefaults() {
|
||||
return {
|
||||
tapToDismiss: true,
|
||||
toastClass: 'toast',
|
||||
containerId: 'toast-container',
|
||||
debug: false,
|
||||
|
||||
showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
|
||||
showDuration: 300,
|
||||
showEasing: 'swing', //swing and linear are built into jQuery
|
||||
onShown: undefined,
|
||||
hideMethod: 'fadeOut',
|
||||
hideDuration: 1000,
|
||||
hideEasing: 'swing',
|
||||
onHidden: undefined,
|
||||
|
||||
extendedTimeOut: 1000,
|
||||
iconClasses: {
|
||||
error: 'toast-error',
|
||||
info: 'toast-info',
|
||||
success: 'toast-success',
|
||||
warning: 'toast-warning'
|
||||
},
|
||||
iconClass: 'toast-info',
|
||||
positionClass: 'toast-top-right',
|
||||
timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky
|
||||
titleClass: 'toast-title',
|
||||
messageClass: 'toast-message',
|
||||
target: 'body',
|
||||
closeHtml: '<button type="button">×</button>',
|
||||
newestOnTop: true,
|
||||
preventDuplicates: false,
|
||||
progressBar: false
|
||||
};
|
||||
}
|
||||
|
||||
function publish(args) {
|
||||
if (!listener) { return; }
|
||||
listener(args);
|
||||
}
|
||||
|
||||
function notify(map) {
|
||||
var options = getOptions();
|
||||
var iconClass = map.iconClass || options.iconClass;
|
||||
|
||||
if (typeof (map.optionsOverride) !== 'undefined') {
|
||||
options = $.extend(options, map.optionsOverride);
|
||||
iconClass = map.optionsOverride.iconClass || iconClass;
|
||||
}
|
||||
|
||||
if (shouldExit(options, map)) { return; }
|
||||
|
||||
toastId++;
|
||||
|
||||
$container = getContainer(options, true);
|
||||
|
||||
var intervalId = null;
|
||||
var $toastElement = $('<div/>');
|
||||
var $titleElement = $('<div/>');
|
||||
var $messageElement = $('<div/>');
|
||||
var $progressElement = $('<div/>');
|
||||
var $closeElement = $(options.closeHtml);
|
||||
var progressBar = {
|
||||
intervalId: null,
|
||||
hideEta: null,
|
||||
maxHideTime: null
|
||||
};
|
||||
var response = {
|
||||
toastId: toastId,
|
||||
state: 'visible',
|
||||
startTime: new Date(),
|
||||
options: options,
|
||||
map: map
|
||||
};
|
||||
|
||||
personalizeToast();
|
||||
|
||||
displayToast();
|
||||
|
||||
handleEvents();
|
||||
|
||||
publish(response);
|
||||
|
||||
if (options.debug && console) {
|
||||
console.log(response);
|
||||
}
|
||||
|
||||
return $toastElement;
|
||||
|
||||
function personalizeToast() {
|
||||
setIcon();
|
||||
setTitle();
|
||||
setMessage();
|
||||
setCloseButton();
|
||||
setProgressBar();
|
||||
setSequence();
|
||||
}
|
||||
|
||||
function handleEvents() {
|
||||
$toastElement.hover(stickAround, delayedHideToast);
|
||||
if (!options.onclick && options.tapToDismiss) {
|
||||
$toastElement.click(hideToast);
|
||||
}
|
||||
|
||||
if (options.closeButton && $closeElement) {
|
||||
$closeElement.click(function (event) {
|
||||
if (event.stopPropagation) {
|
||||
event.stopPropagation();
|
||||
} else if (event.cancelBubble !== undefined && event.cancelBubble !== true) {
|
||||
event.cancelBubble = true;
|
||||
}
|
||||
hideToast(true);
|
||||
});
|
||||
}
|
||||
|
||||
if (options.onclick) {
|
||||
$toastElement.click(function () {
|
||||
options.onclick();
|
||||
hideToast();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function displayToast() {
|
||||
$toastElement.hide();
|
||||
|
||||
$toastElement[options.showMethod](
|
||||
{duration: options.showDuration, easing: options.showEasing, complete: options.onShown}
|
||||
);
|
||||
|
||||
if (options.timeOut > 0) {
|
||||
intervalId = setTimeout(hideToast, options.timeOut);
|
||||
progressBar.maxHideTime = parseFloat(options.timeOut);
|
||||
progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
|
||||
if (options.progressBar) {
|
||||
progressBar.intervalId = setInterval(updateProgress, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setIcon() {
|
||||
if (map.iconClass) {
|
||||
$toastElement.addClass(options.toastClass).addClass(iconClass);
|
||||
}
|
||||
}
|
||||
|
||||
function setSequence() {
|
||||
if (options.newestOnTop) {
|
||||
$container.prepend($toastElement);
|
||||
} else {
|
||||
$container.append($toastElement);
|
||||
}
|
||||
}
|
||||
|
||||
function setTitle() {
|
||||
if (map.title) {
|
||||
$titleElement.append(map.title).addClass(options.titleClass);
|
||||
$toastElement.append($titleElement);
|
||||
}
|
||||
}
|
||||
|
||||
function setMessage() {
|
||||
if (map.message) {
|
||||
$messageElement.append(map.message).addClass(options.messageClass);
|
||||
$toastElement.append($messageElement);
|
||||
}
|
||||
}
|
||||
|
||||
function setCloseButton() {
|
||||
if (options.closeButton) {
|
||||
$closeElement.addClass('toast-close-button').attr('role', 'button');
|
||||
$toastElement.prepend($closeElement);
|
||||
}
|
||||
}
|
||||
|
||||
function setProgressBar() {
|
||||
if (options.progressBar) {
|
||||
$progressElement.addClass('toast-progress');
|
||||
$toastElement.prepend($progressElement);
|
||||
}
|
||||
}
|
||||
|
||||
function shouldExit(options, map) {
|
||||
if (options.preventDuplicates) {
|
||||
if (map.message === previousToast) {
|
||||
return true;
|
||||
} else {
|
||||
previousToast = map.message;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function hideToast(override) {
|
||||
if ($(':focus', $toastElement).length && !override) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(progressBar.intervalId);
|
||||
return $toastElement[options.hideMethod]({
|
||||
duration: options.hideDuration,
|
||||
easing: options.hideEasing,
|
||||
complete: function () {
|
||||
removeToast($toastElement);
|
||||
if (options.onHidden && response.state !== 'hidden') {
|
||||
options.onHidden();
|
||||
}
|
||||
response.state = 'hidden';
|
||||
response.endTime = new Date();
|
||||
publish(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function delayedHideToast() {
|
||||
if (options.timeOut > 0 || options.extendedTimeOut > 0) {
|
||||
intervalId = setTimeout(hideToast, options.extendedTimeOut);
|
||||
progressBar.maxHideTime = parseFloat(options.extendedTimeOut);
|
||||
progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
|
||||
}
|
||||
}
|
||||
|
||||
function stickAround() {
|
||||
clearTimeout(intervalId);
|
||||
progressBar.hideEta = 0;
|
||||
$toastElement.stop(true, true)[options.showMethod](
|
||||
{duration: options.showDuration, easing: options.showEasing}
|
||||
);
|
||||
}
|
||||
|
||||
function updateProgress() {
|
||||
var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100;
|
||||
$progressElement.width(percentage + '%');
|
||||
}
|
||||
}
|
||||
|
||||
function getOptions() {
|
||||
return $.extend({}, getDefaults(), toastr.options);
|
||||
}
|
||||
|
||||
function removeToast($toastElement) {
|
||||
if (!$container) { $container = getContainer(); }
|
||||
if ($toastElement.is(':visible')) {
|
||||
return;
|
||||
}
|
||||
$toastElement.remove();
|
||||
$toastElement = null;
|
||||
if ($container.children().length === 0) {
|
||||
$container.remove();
|
||||
previousToast = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
});
|
||||
}(typeof define === 'function' && define.amd ? define : function (deps, factory) {
|
||||
if (typeof module !== 'undefined' && module.exports) { //Node
|
||||
module.exports = factory(require('jquery'));
|
||||
} else {
|
||||
window['toastr'] = factory(window['jQuery']);
|
||||
}
|
||||
}));
|
||||
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Toastr
|
||||
* Copyright 2012-2015
|
||||
* Authors: John Papa, Hans Fjällemark, and Tim Ferrell.
|
||||
* All Rights Reserved.
|
||||
* Use, reproduction, distribution, and modification of this code is subject to the terms and
|
||||
* conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* ARIA Support: Greta Krafsig
|
||||
*
|
||||
* Project: https://github.com/CodeSeven/toastr
|
||||
*/
|
||||
/* global define */
|
||||
(function (define) {
|
||||
define(['jquery'], function ($) {
|
||||
return (function () {
|
||||
var $container;
|
||||
var listener;
|
||||
var toastId = 0;
|
||||
var toastType = {
|
||||
error: 'error',
|
||||
info: 'info',
|
||||
success: 'success',
|
||||
warning: 'warning'
|
||||
};
|
||||
|
||||
var toastr = {
|
||||
clear: clear,
|
||||
remove: remove,
|
||||
error: error,
|
||||
getContainer: getContainer,
|
||||
info: info,
|
||||
options: {},
|
||||
subscribe: subscribe,
|
||||
success: success,
|
||||
version: '2.1.2',
|
||||
warning: warning
|
||||
};
|
||||
|
||||
var previousToast;
|
||||
|
||||
return toastr;
|
||||
|
||||
////////////////
|
||||
|
||||
function error(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.error,
|
||||
iconClass: getOptions().iconClasses.error,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function getContainer(options, create) {
|
||||
if (!options) { options = getOptions(); }
|
||||
$container = $('#' + options.containerId);
|
||||
if ($container.length) {
|
||||
return $container;
|
||||
}
|
||||
if (create) {
|
||||
$container = createContainer(options);
|
||||
}
|
||||
return $container;
|
||||
}
|
||||
|
||||
function info(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.info,
|
||||
iconClass: getOptions().iconClasses.info,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function subscribe(callback) {
|
||||
listener = callback;
|
||||
}
|
||||
|
||||
function success(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.success,
|
||||
iconClass: getOptions().iconClasses.success,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function warning(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.warning,
|
||||
iconClass: getOptions().iconClasses.warning,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function clear($toastElement, clearOptions) {
|
||||
var options = getOptions();
|
||||
if (!$container) { getContainer(options); }
|
||||
if (!clearToast($toastElement, options, clearOptions)) {
|
||||
clearContainer(options);
|
||||
}
|
||||
}
|
||||
|
||||
function remove($toastElement) {
|
||||
var options = getOptions();
|
||||
if (!$container) { getContainer(options); }
|
||||
if ($toastElement && $(':focus', $toastElement).length === 0) {
|
||||
removeToast($toastElement);
|
||||
return;
|
||||
}
|
||||
if ($container.children().length) {
|
||||
$container.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// internal functions
|
||||
|
||||
function clearContainer (options) {
|
||||
var toastsToClear = $container.children();
|
||||
for (var i = toastsToClear.length - 1; i >= 0; i--) {
|
||||
clearToast($(toastsToClear[i]), options);
|
||||
}
|
||||
}
|
||||
|
||||
function clearToast ($toastElement, options, clearOptions) {
|
||||
var force = clearOptions && clearOptions.force ? clearOptions.force : false;
|
||||
if ($toastElement && (force || $(':focus', $toastElement).length === 0)) {
|
||||
$toastElement[options.hideMethod]({
|
||||
duration: options.hideDuration,
|
||||
easing: options.hideEasing,
|
||||
complete: function () { removeToast($toastElement); }
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function createContainer(options) {
|
||||
$container = $('<div/>')
|
||||
.attr('id', options.containerId)
|
||||
.addClass(options.positionClass)
|
||||
.attr('aria-live', 'polite')
|
||||
.attr('role', 'alert');
|
||||
|
||||
$container.appendTo($(options.target));
|
||||
return $container;
|
||||
}
|
||||
|
||||
function getDefaults() {
|
||||
return {
|
||||
tapToDismiss: true,
|
||||
toastClass: 'toast',
|
||||
containerId: 'toast-container',
|
||||
debug: false,
|
||||
|
||||
showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
|
||||
showDuration: 300,
|
||||
showEasing: 'swing', //swing and linear are built into jQuery
|
||||
onShown: undefined,
|
||||
hideMethod: 'fadeOut',
|
||||
hideDuration: 1000,
|
||||
hideEasing: 'swing',
|
||||
onHidden: undefined,
|
||||
closeMethod: false,
|
||||
closeDuration: false,
|
||||
closeEasing: false,
|
||||
|
||||
extendedTimeOut: 1000,
|
||||
iconClasses: {
|
||||
error: 'toast-error',
|
||||
info: 'toast-info',
|
||||
success: 'toast-success',
|
||||
warning: 'toast-warning'
|
||||
},
|
||||
iconClass: 'toast-info',
|
||||
positionClass: 'toast-top-right',
|
||||
timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky
|
||||
titleClass: 'toast-title',
|
||||
messageClass: 'toast-message',
|
||||
escapeHtml: false,
|
||||
target: 'body',
|
||||
closeHtml: '<button type="button">×</button>',
|
||||
newestOnTop: true,
|
||||
preventDuplicates: false,
|
||||
progressBar: false
|
||||
};
|
||||
}
|
||||
|
||||
function publish(args) {
|
||||
if (!listener) { return; }
|
||||
listener(args);
|
||||
}
|
||||
|
||||
function notify(map) {
|
||||
var options = getOptions();
|
||||
var iconClass = map.iconClass || options.iconClass;
|
||||
|
||||
if (typeof (map.optionsOverride) !== 'undefined') {
|
||||
options = $.extend(options, map.optionsOverride);
|
||||
iconClass = map.optionsOverride.iconClass || iconClass;
|
||||
}
|
||||
|
||||
if (shouldExit(options, map)) { return; }
|
||||
|
||||
toastId++;
|
||||
|
||||
$container = getContainer(options, true);
|
||||
|
||||
var intervalId = null;
|
||||
var $toastElement = $('<div/>');
|
||||
var $titleElement = $('<div/>');
|
||||
var $messageElement = $('<div/>');
|
||||
var $progressElement = $('<div/>');
|
||||
var $closeElement = $(options.closeHtml);
|
||||
var progressBar = {
|
||||
intervalId: null,
|
||||
hideEta: null,
|
||||
maxHideTime: null
|
||||
};
|
||||
var response = {
|
||||
toastId: toastId,
|
||||
state: 'visible',
|
||||
startTime: new Date(),
|
||||
options: options,
|
||||
map: map
|
||||
};
|
||||
|
||||
personalizeToast();
|
||||
|
||||
displayToast();
|
||||
|
||||
handleEvents();
|
||||
|
||||
publish(response);
|
||||
|
||||
if (options.debug && console) {
|
||||
console.log(response);
|
||||
}
|
||||
|
||||
return $toastElement;
|
||||
|
||||
function escapeHtml(source) {
|
||||
if (source == null)
|
||||
source = "";
|
||||
|
||||
return new String(source)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
|
||||
function personalizeToast() {
|
||||
setIcon();
|
||||
setTitle();
|
||||
setMessage();
|
||||
setCloseButton();
|
||||
setProgressBar();
|
||||
setSequence();
|
||||
}
|
||||
|
||||
function handleEvents() {
|
||||
$toastElement.hover(stickAround, delayedHideToast);
|
||||
if (!options.onclick && options.tapToDismiss) {
|
||||
$toastElement.click(hideToast);
|
||||
}
|
||||
|
||||
if (options.closeButton && $closeElement) {
|
||||
$closeElement.click(function (event) {
|
||||
if (event.stopPropagation) {
|
||||
event.stopPropagation();
|
||||
} else if (event.cancelBubble !== undefined && event.cancelBubble !== true) {
|
||||
event.cancelBubble = true;
|
||||
}
|
||||
hideToast(true);
|
||||
});
|
||||
}
|
||||
|
||||
if (options.onclick) {
|
||||
$toastElement.click(function (event) {
|
||||
options.onclick(event);
|
||||
hideToast();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function displayToast() {
|
||||
$toastElement.hide();
|
||||
|
||||
$toastElement[options.showMethod](
|
||||
{duration: options.showDuration, easing: options.showEasing, complete: options.onShown}
|
||||
);
|
||||
|
||||
if (options.timeOut > 0) {
|
||||
intervalId = setTimeout(hideToast, options.timeOut);
|
||||
progressBar.maxHideTime = parseFloat(options.timeOut);
|
||||
progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
|
||||
if (options.progressBar) {
|
||||
progressBar.intervalId = setInterval(updateProgress, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setIcon() {
|
||||
if (map.iconClass) {
|
||||
$toastElement.addClass(options.toastClass).addClass(iconClass);
|
||||
}
|
||||
}
|
||||
|
||||
function setSequence() {
|
||||
if (options.newestOnTop) {
|
||||
$container.prepend($toastElement);
|
||||
} else {
|
||||
$container.append($toastElement);
|
||||
}
|
||||
}
|
||||
|
||||
function setTitle() {
|
||||
if (map.title) {
|
||||
$titleElement.append(!options.escapeHtml ? map.title : escapeHtml(map.title)).addClass(options.titleClass);
|
||||
$toastElement.append($titleElement);
|
||||
}
|
||||
}
|
||||
|
||||
function setMessage() {
|
||||
if (map.message) {
|
||||
$messageElement.append(!options.escapeHtml ? map.message : escapeHtml(map.message)).addClass(options.messageClass);
|
||||
$toastElement.append($messageElement);
|
||||
}
|
||||
}
|
||||
|
||||
function setCloseButton() {
|
||||
if (options.closeButton) {
|
||||
$closeElement.addClass('toast-close-button').attr('role', 'button');
|
||||
$toastElement.prepend($closeElement);
|
||||
}
|
||||
}
|
||||
|
||||
function setProgressBar() {
|
||||
if (options.progressBar) {
|
||||
$progressElement.addClass('toast-progress');
|
||||
$toastElement.prepend($progressElement);
|
||||
}
|
||||
}
|
||||
|
||||
function shouldExit(options, map) {
|
||||
if (options.preventDuplicates) {
|
||||
if (map.message === previousToast) {
|
||||
return true;
|
||||
} else {
|
||||
previousToast = map.message;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function hideToast(override) {
|
||||
var method = override && options.closeMethod !== false ? options.closeMethod : options.hideMethod;
|
||||
var duration = override && options.closeDuration !== false ?
|
||||
options.closeDuration : options.hideDuration;
|
||||
var easing = override && options.closeEasing !== false ? options.closeEasing : options.hideEasing;
|
||||
if ($(':focus', $toastElement).length && !override) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(progressBar.intervalId);
|
||||
return $toastElement[method]({
|
||||
duration: duration,
|
||||
easing: easing,
|
||||
complete: function () {
|
||||
removeToast($toastElement);
|
||||
if (options.onHidden && response.state !== 'hidden') {
|
||||
options.onHidden();
|
||||
}
|
||||
response.state = 'hidden';
|
||||
response.endTime = new Date();
|
||||
publish(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function delayedHideToast() {
|
||||
if (options.timeOut > 0 || options.extendedTimeOut > 0) {
|
||||
intervalId = setTimeout(hideToast, options.extendedTimeOut);
|
||||
progressBar.maxHideTime = parseFloat(options.extendedTimeOut);
|
||||
progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
|
||||
}
|
||||
}
|
||||
|
||||
function stickAround() {
|
||||
clearTimeout(intervalId);
|
||||
progressBar.hideEta = 0;
|
||||
$toastElement.stop(true, true)[options.showMethod](
|
||||
{duration: options.showDuration, easing: options.showEasing}
|
||||
);
|
||||
}
|
||||
|
||||
function updateProgress() {
|
||||
var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100;
|
||||
$progressElement.width(percentage + '%');
|
||||
}
|
||||
}
|
||||
|
||||
function getOptions() {
|
||||
return $.extend({}, getDefaults(), toastr.options);
|
||||
}
|
||||
|
||||
function removeToast($toastElement) {
|
||||
if (!$container) { $container = getContainer(); }
|
||||
if ($toastElement.is(':visible')) {
|
||||
return;
|
||||
}
|
||||
$toastElement.remove();
|
||||
$toastElement = null;
|
||||
if ($container.children().length === 0) {
|
||||
$container.remove();
|
||||
previousToast = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
});
|
||||
}(typeof define === 'function' && define.amd ? define : function (deps, factory) {
|
||||
if (typeof module !== 'undefined' && module.exports) { //Node
|
||||
module.exports = factory(require('jquery'));
|
||||
} else {
|
||||
window.toastr = factory(window.jQuery);
|
||||
}
|
||||
}));
|
||||
+5
File diff suppressed because one or more lines are too long
@@ -0,0 +1,64 @@
|
||||
// VIDEO BACKGROUND
|
||||
|
||||
$( document ).ready(function() {
|
||||
|
||||
scaleVideoContainer();
|
||||
|
||||
initBannerVideoSize('.video-container .poster img');
|
||||
initBannerVideoSize('.video-container .filter');
|
||||
initBannerVideoSize('.video-container video');
|
||||
|
||||
$(window).on('resize', function() {
|
||||
scaleVideoContainer();
|
||||
scaleBannerVideoSize('.video-container .poster img');
|
||||
scaleBannerVideoSize('.video-container .filter');
|
||||
scaleBannerVideoSize('.video-container video');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function scaleVideoContainer() {
|
||||
|
||||
var height = $(window).height() + 5;
|
||||
var unitHeight = parseInt(height) + 'px';
|
||||
$('.homepage-hero-module').css('height',unitHeight);
|
||||
|
||||
}
|
||||
|
||||
function initBannerVideoSize(element){
|
||||
|
||||
$(element).each(function(){
|
||||
$(this).data('height', $(this).height());
|
||||
$(this).data('width', $(this).width());
|
||||
});
|
||||
|
||||
scaleBannerVideoSize(element);
|
||||
|
||||
}
|
||||
|
||||
function scaleBannerVideoSize(element){
|
||||
|
||||
var windowWidth = $(window).width(),
|
||||
windowHeight = $(window).height() + 5,
|
||||
videoWidth,
|
||||
videoHeight;
|
||||
|
||||
/* console.log(windowHeight); */
|
||||
|
||||
$(element).each(function(){
|
||||
var videoAspectRatio = $(this).data('height')/$(this).data('width');
|
||||
|
||||
$(this).width(windowWidth);
|
||||
|
||||
if(windowWidth < 1000){
|
||||
videoHeight = windowHeight;
|
||||
videoWidth = videoHeight / videoAspectRatio;
|
||||
$(this).css({'margin-top' : 0, 'margin-left' : -(videoWidth - windowWidth) / 2 + 'px'});
|
||||
|
||||
$(this).width(videoWidth).height(videoHeight);
|
||||
}
|
||||
|
||||
$('.homepage-hero-module .video-container video').addClass('fadeIn animated');
|
||||
|
||||
});
|
||||
}
|
||||
Executable
+597
@@ -0,0 +1,597 @@
|
||||
/*!
|
||||
* Waves v0.7.5
|
||||
* http://fian.my.id/Waves
|
||||
*
|
||||
* Copyright 2014-2016 Alfiana E. Sibuea and other contributors
|
||||
* Released under the MIT license
|
||||
* https://github.com/fians/Waves/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
;
|
||||
(function (window, factory) {
|
||||
'use strict';
|
||||
|
||||
// AMD. Register as an anonymous module. Wrap in function so we have access
|
||||
// to root via `this`.
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([], function () {
|
||||
return factory.apply(window);
|
||||
});
|
||||
}
|
||||
|
||||
// Node. Does not work with strict CommonJS, but only CommonJS-like
|
||||
// environments that support module.exports, like Node.
|
||||
else if (typeof exports === 'object') {
|
||||
module.exports = factory.call(window);
|
||||
}
|
||||
|
||||
// Browser globals.
|
||||
else {
|
||||
window.Waves = factory.call(window);
|
||||
}
|
||||
})(typeof global === 'object' ? global : this, function () {
|
||||
'use strict';
|
||||
|
||||
var Waves = Waves || {};
|
||||
var $$ = document.querySelectorAll.bind(document);
|
||||
var toString = Object.prototype.toString;
|
||||
var isTouchAvailable = 'ontouchstart' in window;
|
||||
|
||||
|
||||
// Find exact position of element
|
||||
function isWindow(obj) {
|
||||
return obj !== null && obj === obj.window;
|
||||
}
|
||||
|
||||
function getWindow(elem) {
|
||||
return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
|
||||
}
|
||||
|
||||
function isObject(value) {
|
||||
var type = typeof value;
|
||||
return type === 'function' || type === 'object' && !!value;
|
||||
}
|
||||
|
||||
function isDOMNode(obj) {
|
||||
return isObject(obj) && obj.nodeType > 0;
|
||||
}
|
||||
|
||||
function getWavesElements(nodes) {
|
||||
var stringRepr = toString.call(nodes);
|
||||
|
||||
if (stringRepr === '[object String]') {
|
||||
return $$(nodes);
|
||||
} else if (isObject(nodes) && /^\[object (Array|HTMLCollection|NodeList|Object)\]$/.test(stringRepr) && nodes.hasOwnProperty('length')) {
|
||||
return nodes;
|
||||
} else if (isDOMNode(nodes)) {
|
||||
return [nodes];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
function offset(elem) {
|
||||
var docElem, win,
|
||||
box = {
|
||||
top: 0,
|
||||
left: 0
|
||||
},
|
||||
doc = elem && elem.ownerDocument;
|
||||
|
||||
docElem = doc.documentElement;
|
||||
|
||||
if (typeof elem.getBoundingClientRect !== typeof undefined) {
|
||||
box = elem.getBoundingClientRect();
|
||||
}
|
||||
win = getWindow(doc);
|
||||
return {
|
||||
top: box.top + win.pageYOffset - docElem.clientTop,
|
||||
left: box.left + win.pageXOffset - docElem.clientLeft
|
||||
};
|
||||
}
|
||||
|
||||
function convertStyle(styleObj) {
|
||||
var style = '';
|
||||
|
||||
for (var prop in styleObj) {
|
||||
if (styleObj.hasOwnProperty(prop)) {
|
||||
style += (prop + ':' + styleObj[prop] + ';');
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
var Effect = {
|
||||
|
||||
// Effect duration
|
||||
duration: 750,
|
||||
|
||||
// Effect delay (check for scroll before showing effect)
|
||||
delay: 200,
|
||||
|
||||
show: function (e, element, velocity) {
|
||||
|
||||
// Disable right click
|
||||
if (e.button === 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
element = element || this;
|
||||
|
||||
// Create ripple
|
||||
var ripple = document.createElement('div');
|
||||
ripple.className = 'waves-ripple waves-rippling';
|
||||
element.appendChild(ripple);
|
||||
|
||||
// Get click coordinate and element width
|
||||
var pos = offset(element);
|
||||
var relativeY = 0;
|
||||
var relativeX = 0;
|
||||
// Support for touch devices
|
||||
if ('touches' in e && e.touches.length) {
|
||||
relativeY = (e.touches[0].pageY - pos.top);
|
||||
relativeX = (e.touches[0].pageX - pos.left);
|
||||
}
|
||||
//Normal case
|
||||
else {
|
||||
relativeY = (e.pageY - pos.top);
|
||||
relativeX = (e.pageX - pos.left);
|
||||
}
|
||||
// Support for synthetic events
|
||||
relativeX = relativeX >= 0 ? relativeX : 0;
|
||||
relativeY = relativeY >= 0 ? relativeY : 0;
|
||||
|
||||
var scale = 'scale(' + ((element.clientWidth / 100) * 3) + ')';
|
||||
var translate = 'translate(0,0)';
|
||||
|
||||
if (velocity) {
|
||||
translate = 'translate(' + (velocity.x) + 'px, ' + (velocity.y) + 'px)';
|
||||
}
|
||||
|
||||
// Attach data to element
|
||||
ripple.setAttribute('data-hold', Date.now());
|
||||
ripple.setAttribute('data-x', relativeX);
|
||||
ripple.setAttribute('data-y', relativeY);
|
||||
ripple.setAttribute('data-scale', scale);
|
||||
ripple.setAttribute('data-translate', translate);
|
||||
|
||||
// Set ripple position
|
||||
var rippleStyle = {
|
||||
top: relativeY + 'px',
|
||||
left: relativeX + 'px'
|
||||
};
|
||||
|
||||
ripple.classList.add('waves-notransition');
|
||||
ripple.setAttribute('style', convertStyle(rippleStyle));
|
||||
ripple.classList.remove('waves-notransition');
|
||||
|
||||
// Scale the ripple
|
||||
rippleStyle['-webkit-transform'] = scale + ' ' + translate;
|
||||
rippleStyle['-moz-transform'] = scale + ' ' + translate;
|
||||
rippleStyle['-ms-transform'] = scale + ' ' + translate;
|
||||
rippleStyle['-o-transform'] = scale + ' ' + translate;
|
||||
rippleStyle.transform = scale + ' ' + translate;
|
||||
rippleStyle.opacity = '1';
|
||||
|
||||
var duration = e.type === 'mousemove' ? 2500 : Effect.duration;
|
||||
rippleStyle['-webkit-transition-duration'] = duration + 'ms';
|
||||
rippleStyle['-moz-transition-duration'] = duration + 'ms';
|
||||
rippleStyle['-o-transition-duration'] = duration + 'ms';
|
||||
rippleStyle['transition-duration'] = duration + 'ms';
|
||||
|
||||
ripple.setAttribute('style', convertStyle(rippleStyle));
|
||||
},
|
||||
|
||||
hide: function (e, element) {
|
||||
element = element || this;
|
||||
|
||||
var ripples = element.getElementsByClassName('waves-rippling');
|
||||
|
||||
for (var i = 0, len = ripples.length; i < len; i++) {
|
||||
removeRipple(e, element, ripples[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Collection of wrapper for HTML element that only have single tag
|
||||
* like <input> and <img>
|
||||
*/
|
||||
var TagWrapper = {
|
||||
|
||||
// Wrap <input> tag so it can perform the effect
|
||||
input: function (element) {
|
||||
|
||||
var parent = element.parentNode;
|
||||
|
||||
// If input already have parent just pass through
|
||||
if (parent.tagName.toLowerCase() === 'div' && parent.classList.contains('waves-effect')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Put element class and style to the specified parent
|
||||
var wrapper = document.createElement('div');
|
||||
wrapper.className = 'waves-input-wrapper';
|
||||
// element.className = element.className + ' waves-button-input';
|
||||
|
||||
// Put element as child
|
||||
parent.replaceChild(wrapper, element);
|
||||
wrapper.appendChild(element);
|
||||
|
||||
// Apply element color and background color to wrapper
|
||||
var elementStyle = window.getComputedStyle(element, null);
|
||||
var color = elementStyle.color;
|
||||
var backgroundColor = elementStyle.backgroundColor;
|
||||
|
||||
// wrapper.setAttribute('style', 'color:' + color + ';background:' + backgroundColor);
|
||||
// element.setAttribute('style', 'background-color:rgba(0,0,0,0);');
|
||||
|
||||
},
|
||||
|
||||
// Wrap <img> tag so it can perform the effect
|
||||
img: function (element) {
|
||||
|
||||
var parent = element.parentNode;
|
||||
|
||||
// If input already have parent just pass through
|
||||
if (parent.tagName.toLowerCase() === 'i' && parent.classList.contains('waves-effect')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Put element as child
|
||||
var wrapper = document.createElement('i');
|
||||
parent.replaceChild(wrapper, element);
|
||||
wrapper.appendChild(element);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the effect and remove the ripple. Must be
|
||||
* a separate function to pass the JSLint...
|
||||
*/
|
||||
function removeRipple(e, el, ripple) {
|
||||
|
||||
// Check if the ripple still exist
|
||||
if (!ripple) {
|
||||
return;
|
||||
}
|
||||
|
||||
ripple.classList.remove('waves-rippling');
|
||||
|
||||
var relativeX = ripple.getAttribute('data-x');
|
||||
var relativeY = ripple.getAttribute('data-y');
|
||||
var scale = ripple.getAttribute('data-scale');
|
||||
var translate = ripple.getAttribute('data-translate');
|
||||
|
||||
// Get delay beetween mousedown and mouse leave
|
||||
var diff = Date.now() - Number(ripple.getAttribute('data-hold'));
|
||||
var delay = 350 - diff;
|
||||
|
||||
if (delay < 0) {
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
if (e.type === 'mousemove') {
|
||||
delay = 150;
|
||||
}
|
||||
|
||||
// Fade out ripple after delay
|
||||
var duration = e.type === 'mousemove' ? 2500 : Effect.duration;
|
||||
|
||||
setTimeout(function () {
|
||||
|
||||
var style = {
|
||||
top: relativeY + 'px',
|
||||
left: relativeX + 'px',
|
||||
opacity: '0',
|
||||
|
||||
// Duration
|
||||
'-webkit-transition-duration': duration + 'ms',
|
||||
'-moz-transition-duration': duration + 'ms',
|
||||
'-o-transition-duration': duration + 'ms',
|
||||
'transition-duration': duration + 'ms',
|
||||
'-webkit-transform': scale + ' ' + translate,
|
||||
'-moz-transform': scale + ' ' + translate,
|
||||
'-ms-transform': scale + ' ' + translate,
|
||||
'-o-transform': scale + ' ' + translate,
|
||||
'transform': scale + ' ' + translate
|
||||
};
|
||||
|
||||
ripple.setAttribute('style', convertStyle(style));
|
||||
|
||||
setTimeout(function () {
|
||||
try {
|
||||
el.removeChild(ripple);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}, duration);
|
||||
|
||||
}, delay);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disable mousedown event for 500ms during and after touch
|
||||
*/
|
||||
var TouchHandler = {
|
||||
|
||||
/* uses an integer rather than bool so there's no issues with
|
||||
* needing to clear timeouts if another touch event occurred
|
||||
* within the 500ms. Cannot mouseup between touchstart and
|
||||
* touchend, nor in the 500ms after touchend. */
|
||||
touches: 0,
|
||||
|
||||
allowEvent: function (e) {
|
||||
|
||||
var allow = true;
|
||||
|
||||
if (/^(mousedown|mousemove)$/.test(e.type) && TouchHandler.touches) {
|
||||
allow = false;
|
||||
}
|
||||
|
||||
return allow;
|
||||
},
|
||||
registerEvent: function (e) {
|
||||
var eType = e.type;
|
||||
|
||||
if (eType === 'touchstart') {
|
||||
|
||||
TouchHandler.touches += 1; // push
|
||||
|
||||
} else if (/^(touchend|touchcancel)$/.test(eType)) {
|
||||
|
||||
setTimeout(function () {
|
||||
if (TouchHandler.touches) {
|
||||
TouchHandler.touches -= 1; // pop after 500ms
|
||||
}
|
||||
}, 500);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Delegated click handler for .waves-effect element.
|
||||
* returns null when .waves-effect element not in "click tree"
|
||||
*/
|
||||
function getWavesEffectElement(e) {
|
||||
|
||||
if (TouchHandler.allowEvent(e) === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var element = null;
|
||||
var target = e.target || e.srcElement;
|
||||
|
||||
while (target.parentElement !== null) {
|
||||
if (target.classList.contains('waves-effect') && (!(target instanceof SVGElement))) {
|
||||
element = target;
|
||||
break;
|
||||
}
|
||||
target = target.parentElement;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bubble the click and show effect if .waves-effect elem was found
|
||||
*/
|
||||
function showEffect(e) {
|
||||
|
||||
// Disable effect if element has "disabled" property on it
|
||||
// In some cases, the event is not triggered by the current element
|
||||
// if (e.target.getAttribute('disabled') !== null) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
var element = getWavesEffectElement(e);
|
||||
|
||||
if (element !== null) {
|
||||
|
||||
// Make it sure the element has either disabled property, disabled attribute or 'disabled' class
|
||||
if (element.disabled || element.getAttribute('disabled') || element.classList.contains('disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
TouchHandler.registerEvent(e);
|
||||
|
||||
if (e.type === 'touchstart' && Effect.delay) {
|
||||
|
||||
var hidden = false;
|
||||
|
||||
var timer = setTimeout(function () {
|
||||
timer = null;
|
||||
Effect.show(e, element);
|
||||
}, Effect.delay);
|
||||
|
||||
var hideEffect = function (hideEvent) {
|
||||
|
||||
// if touch hasn't moved, and effect not yet started: start effect now
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
Effect.show(e, element);
|
||||
}
|
||||
if (!hidden) {
|
||||
hidden = true;
|
||||
Effect.hide(hideEvent, element);
|
||||
}
|
||||
};
|
||||
|
||||
var touchMove = function (moveEvent) {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
hideEffect(moveEvent);
|
||||
};
|
||||
|
||||
element.addEventListener('touchmove', touchMove, false);
|
||||
element.addEventListener('touchend', hideEffect, false);
|
||||
element.addEventListener('touchcancel', hideEffect, false);
|
||||
|
||||
} else {
|
||||
|
||||
Effect.show(e, element);
|
||||
|
||||
if (isTouchAvailable) {
|
||||
element.addEventListener('touchend', Effect.hide, false);
|
||||
element.addEventListener('touchcancel', Effect.hide, false);
|
||||
}
|
||||
|
||||
element.addEventListener('mouseup', Effect.hide, false);
|
||||
element.addEventListener('mouseleave', Effect.hide, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Waves.init = function (options) {
|
||||
var body = document.body;
|
||||
|
||||
options = options || {};
|
||||
|
||||
if ('duration' in options) {
|
||||
Effect.duration = options.duration;
|
||||
}
|
||||
|
||||
if ('delay' in options) {
|
||||
Effect.delay = options.delay;
|
||||
}
|
||||
|
||||
if (isTouchAvailable) {
|
||||
body.addEventListener('touchstart', showEffect, false);
|
||||
body.addEventListener('touchcancel', TouchHandler.registerEvent, false);
|
||||
body.addEventListener('touchend', TouchHandler.registerEvent, false);
|
||||
}
|
||||
|
||||
body.addEventListener('mousedown', showEffect, false);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attach Waves to dynamically loaded inputs, or add .waves-effect and other
|
||||
* waves classes to a set of elements. Set drag to true if the ripple mouseover
|
||||
* or skimming effect should be applied to the elements.
|
||||
*/
|
||||
Waves.attach = function (elements, classes) {
|
||||
|
||||
elements = getWavesElements(elements);
|
||||
|
||||
if (toString.call(classes) === '[object Array]') {
|
||||
classes = classes.join(' ');
|
||||
}
|
||||
|
||||
classes = classes ? ' ' + classes : '';
|
||||
|
||||
var element, tagName;
|
||||
|
||||
for (var i = 0, len = elements.length; i < len; i++) {
|
||||
|
||||
element = elements[i];
|
||||
tagName = element.tagName.toLowerCase();
|
||||
|
||||
if (['input', 'img'].indexOf(tagName) !== -1) {
|
||||
TagWrapper[tagName](element);
|
||||
element = element.parentElement;
|
||||
}
|
||||
|
||||
if (element.className.indexOf('waves-effect') === -1) {
|
||||
element.className += ' waves-effect' + classes;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cause a ripple to appear in an element via code.
|
||||
*/
|
||||
Waves.ripple = function (elements, options) {
|
||||
elements = getWavesElements(elements);
|
||||
var elementsLen = elements.length;
|
||||
|
||||
options = options || {};
|
||||
options.wait = options.wait || 0;
|
||||
options.position = options.position || null; // default = centre of element
|
||||
|
||||
|
||||
if (elementsLen) {
|
||||
var element, pos, off, centre = {},
|
||||
i = 0;
|
||||
var mousedown = {
|
||||
type: 'mousedown',
|
||||
button: 1
|
||||
};
|
||||
var hideRipple = function (mouseup, element) {
|
||||
return function () {
|
||||
Effect.hide(mouseup, element);
|
||||
};
|
||||
};
|
||||
|
||||
for (; i < elementsLen; i++) {
|
||||
element = elements[i];
|
||||
pos = options.position || {
|
||||
x: element.clientWidth / 2,
|
||||
y: element.clientHeight / 2
|
||||
};
|
||||
|
||||
off = offset(element);
|
||||
centre.x = off.left + pos.x;
|
||||
centre.y = off.top + pos.y;
|
||||
|
||||
mousedown.pageX = centre.x;
|
||||
mousedown.pageY = centre.y;
|
||||
|
||||
Effect.show(mousedown, element);
|
||||
|
||||
if (options.wait >= 0 && options.wait !== null) {
|
||||
var mouseup = {
|
||||
type: 'mouseup',
|
||||
button: 1
|
||||
};
|
||||
|
||||
setTimeout(hideRipple(mouseup, element), options.wait);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove all ripples from an element.
|
||||
*/
|
||||
Waves.calm = function (elements) {
|
||||
elements = getWavesElements(elements);
|
||||
var mouseup = {
|
||||
type: 'mouseup',
|
||||
button: 1
|
||||
};
|
||||
|
||||
for (var i = 0, len = elements.length; i < len; i++) {
|
||||
Effect.hide(mouseup, elements[i]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deprecated API fallback
|
||||
*/
|
||||
Waves.displayEffect = function (options) {
|
||||
console.error('Waves.displayEffect() has been deprecated and will be removed in future version. Please use Waves.init() to initialize Waves effect');
|
||||
Waves.init(options);
|
||||
};
|
||||
|
||||
return Waves;
|
||||
});
|
||||
|
||||
//Initialization
|
||||
Waves.attach('.btn:not(.btn-flat), .btn-floating', ['waves-light']);
|
||||
Waves.attach('.btn-flat', ['waves-effect']);
|
||||
Waves.attach('.view .mask', ['waves-light']);
|
||||
Waves.attach('.waves-light', ['waves-light']);
|
||||
Waves.attach('.navbar-nav a:not(.navbar-brand), .nav-icons li a, .navbar form, .nav-tabs .nav-item', ['waves-light']);
|
||||
Waves.attach('.pager li a', ['waves-light']);
|
||||
Waves.attach('.pagination .page-item .page-link', ['waves-effect']);
|
||||
Waves.init();
|
||||
Executable
+180
@@ -0,0 +1,180 @@
|
||||
'use strict';
|
||||
|
||||
var WOW;
|
||||
|
||||
(function($) {
|
||||
|
||||
WOW = function WOW() {
|
||||
|
||||
return {
|
||||
|
||||
init: function init() {
|
||||
|
||||
var animationName = [];
|
||||
|
||||
var once = 1;
|
||||
|
||||
function mdbWow() {
|
||||
|
||||
var windowHeight = window.innerHeight;
|
||||
var scroll = window.scrollY;
|
||||
|
||||
$('.wow').each(function() {
|
||||
|
||||
if ($(this).css('visibility') == 'visible') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (windowHeight + scroll - 100 > getOffset(this) && scroll < getOffset(this) || windowHeight + scroll - 100 > getOffset(this) + $(this).height() && scroll < getOffset(this) + $(this).height() || windowHeight + scroll == $(document).height() && getOffset(this) + 100 > $(document).height()) {
|
||||
|
||||
var index = $(this).index('.wow');
|
||||
|
||||
var delay = $(this).attr('data-wow-delay');
|
||||
|
||||
if (delay) {
|
||||
|
||||
delay = $(this).attr('data-wow-delay').slice(0, -1
|
||||
|
||||
);
|
||||
var self = this;
|
||||
|
||||
var timeout = parseFloat(delay) * 1000;
|
||||
|
||||
$(self).addClass('animated');
|
||||
$(self).css({ 'visibility': 'visible' });
|
||||
$(self).css({ 'animation-delay': delay });
|
||||
$(self).css({ 'animation-name': animationName[index] });
|
||||
|
||||
var removeTime = $(this).css('animation-duration').slice(0, -1) * 1000;
|
||||
|
||||
if ($(this).attr('data-wow-delay')) {
|
||||
|
||||
removeTime += $(this).attr('data-wow-delay').slice(0, -1) * 1000;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
$(self).removeClass('animated');
|
||||
}, removeTime);
|
||||
} else {
|
||||
|
||||
$(this).addClass('animated');
|
||||
$(this).css({ 'visibility': 'visible' });
|
||||
$(this).css({ 'animation-name': animationName[index] });
|
||||
|
||||
var removeTime = $(this).css('animation-duration').slice(0, -1) * 1000;
|
||||
|
||||
var self = this;
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
$(self).removeClass('animated');
|
||||
}, removeTime);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function appear() {
|
||||
|
||||
$('.wow').each(function() {
|
||||
|
||||
var index = $(this).index('.wow');
|
||||
|
||||
var delay = $(this).attr('data-wow-delay');
|
||||
|
||||
if (delay) {
|
||||
|
||||
delay = $(this).attr('data-wow-delay').slice(0, -1);
|
||||
|
||||
var timeout = parseFloat(delay) * 1000;
|
||||
|
||||
$(this).addClass('animated');
|
||||
$(this).css({ 'visibility': 'visible' });
|
||||
$(this).css({ 'animation-delay': delay + 's' });
|
||||
$(this).css({ 'animation-name': animationName[index] });
|
||||
} else {
|
||||
|
||||
$(this).addClass('animated');
|
||||
$(this).css({ 'visibility': 'visible' });
|
||||
$(this).css({ 'animation-name': animationName[index] });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function hide() {
|
||||
|
||||
var windowHeight = window.innerHeight;
|
||||
var scroll = window.scrollY;
|
||||
|
||||
$('.wow.animated').each(function() {
|
||||
|
||||
if (windowHeight + scroll - 100 > getOffset(this) && scroll > getOffset(this) + 100 || windowHeight + scroll - 100 < getOffset(this) && scroll < getOffset(this) + 100 || getOffset(this) + $(this).height > $(document).height() - 100) {
|
||||
|
||||
$(this).removeClass('animated');
|
||||
$(this).css({ 'animation-name': 'none' });
|
||||
$(this).css({ 'visibility': 'hidden' });
|
||||
} else {
|
||||
|
||||
var removeTime = $(this).css('animation-duration').slice(0, -1) * 1000;
|
||||
|
||||
if ($(this).attr('data-wow-delay')) {
|
||||
|
||||
removeTime += $(this).attr('data-wow-delay').slice(0, -1) * 1000;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
$(self).removeClass('animated');
|
||||
}, removeTime);
|
||||
}
|
||||
});
|
||||
|
||||
mdbWow();
|
||||
|
||||
once--;
|
||||
}
|
||||
|
||||
function getOffset(elem) {
|
||||
|
||||
var box = elem.getBoundingClientRect();
|
||||
|
||||
var body = document.body;
|
||||
var docEl = document.documentElement;
|
||||
|
||||
var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
|
||||
|
||||
var clientTop = docEl.clientTop || body.clientTop || 0;
|
||||
|
||||
var top = box.top + scrollTop - clientTop;
|
||||
|
||||
return Math.round(top);
|
||||
}
|
||||
|
||||
$('.wow').each(function() {
|
||||
|
||||
$(this).css({ 'visibility': 'hidden' });
|
||||
animationName[$(this).index('.wow')] = $(this).css('animation-name');
|
||||
$(this).css({ 'animation-name': 'none' });
|
||||
});
|
||||
|
||||
$(window).scroll(function() {
|
||||
|
||||
if (once) {
|
||||
|
||||
hide();
|
||||
} else {
|
||||
|
||||
mdbWow();
|
||||
}
|
||||
});
|
||||
|
||||
appear();
|
||||
}
|
||||
};
|
||||
};
|
||||
})(jQuery);
|
||||
File diff suppressed because it is too large
Load Diff
+3
File diff suppressed because one or more lines are too long
Executable
+93
@@ -0,0 +1,93 @@
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
$.fn.reverse = [].reverse;
|
||||
|
||||
$(document).on('mouseenter.fixedActionBtn', '.fixed-action-btn:not(.click-to-toggle)', function () {
|
||||
|
||||
var $this = $(this);
|
||||
openFABMenu($this);
|
||||
});
|
||||
|
||||
$(document).on('mouseleave.fixedActionBtn', '.fixed-action-btn:not(.click-to-toggle)', function () {
|
||||
|
||||
var $this = $(this);
|
||||
closeFABMenu($this);
|
||||
});
|
||||
|
||||
$(document).on('click.fixedActionBtn', '.fixed-action-btn.click-to-toggle > a', function () {
|
||||
|
||||
var $this = $(this);
|
||||
var $menu = $this.parent();
|
||||
|
||||
if ($menu.hasClass('active')) {
|
||||
|
||||
closeFABMenu($menu);
|
||||
} else {
|
||||
|
||||
openFABMenu($menu);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$.fn.extend({
|
||||
openFAB: function openFAB() {
|
||||
|
||||
openFABMenu($(this));
|
||||
},
|
||||
closeFAB: function closeFAB() {
|
||||
|
||||
closeFABMenu($(this));
|
||||
}
|
||||
});
|
||||
|
||||
var openFABMenu = function openFABMenu(btn) {
|
||||
|
||||
var fab = btn;
|
||||
if (!fab.hasClass('active')) {
|
||||
|
||||
fab.addClass('active');
|
||||
var btnList = document.querySelectorAll('ul .btn-floating');
|
||||
btnList.forEach(function (el) {
|
||||
|
||||
el.classList.add('shown');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var closeFABMenu = function closeFABMenu(btn) {
|
||||
|
||||
var fab = btn;
|
||||
|
||||
fab.removeClass('active');
|
||||
var btnList = document.querySelectorAll('ul .btn-floating');
|
||||
btnList.forEach(function (el) {
|
||||
|
||||
el.classList.remove('shown');
|
||||
});
|
||||
};
|
||||
|
||||
$('.fixed-action-btn').on('click', function (e) {
|
||||
|
||||
e.preventDefault();
|
||||
toggleFABMenu($('.fixed-action-btn'));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
function toggleFABMenu(btn) {
|
||||
|
||||
var elem = btn;
|
||||
|
||||
if (elem.hasClass('active')) {
|
||||
|
||||
closeFABMenu(elem);
|
||||
} else {
|
||||
|
||||
openFABMenu(elem);
|
||||
}
|
||||
}
|
||||
})(jQuery);
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
|
||||
$(document).on('click.card', '.card', function (e) {
|
||||
|
||||
var $reveal = $(this).find('.card-reveal');
|
||||
|
||||
if ($reveal.length) {
|
||||
|
||||
var $clicked = $(e.target);
|
||||
var isTitle = $clicked.is('.card-reveal .card-title');
|
||||
var isTitleIcon = $clicked.is('.card-reveal .card-title i');
|
||||
var isActivator = $clicked.is('.card .activator');
|
||||
var isActivatorIcon = $clicked.is('.card .activator i');
|
||||
|
||||
if (isTitle || isTitleIcon) {
|
||||
|
||||
$reveal.removeClass('show');
|
||||
} else if (isActivator || isActivatorIcon) {
|
||||
|
||||
$reveal.addClass('show');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('.rotate-btn').on('click', function () {
|
||||
|
||||
var cardId = $(this).attr('data-card');
|
||||
$('#' + cardId).toggleClass('flipped');
|
||||
});
|
||||
|
||||
$('.card-share > a').on('click', function (e) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
$(this).toggleClass('share-expanded').parent().find('div').toggleClass('social-reveal-active');
|
||||
});
|
||||
})(jQuery);
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
|
||||
$.fn.characterCounter = function () {
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
var itHasLengthAttribute = $(this).attr('length') !== undefined;
|
||||
|
||||
if (itHasLengthAttribute) {
|
||||
|
||||
$(this).on('input', updateCounter);
|
||||
$(this).on('focus', updateCounter);
|
||||
$(this).on('blur', removeCounterElement);
|
||||
|
||||
addCounterElement($(this));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function updateCounter() {
|
||||
|
||||
var maxLength = Number($(this).attr('length'));
|
||||
var actualLength = Number($(this).val().length);
|
||||
var isValidLength = actualLength <= maxLength;
|
||||
|
||||
$(this).parent().find('span[class="character-counter"]').html(actualLength + '/' + maxLength);
|
||||
|
||||
addInputStyle(isValidLength, $(this));
|
||||
}
|
||||
|
||||
function addCounterElement($input) {
|
||||
|
||||
var $counterElement = $('<span/>').addClass('character-counter').css('float', 'right').css('font-size', '12px').css('height', 1);
|
||||
|
||||
$input.parent().append($counterElement);
|
||||
}
|
||||
|
||||
function removeCounterElement() {
|
||||
|
||||
$(this).parent().find('span[class="character-counter"]').html('');
|
||||
}
|
||||
|
||||
function addInputStyle(isValidLength, $input) {
|
||||
|
||||
var inputHasInvalidClass = $input.hasClass('invalid');
|
||||
if (isValidLength && inputHasInvalidClass) {
|
||||
|
||||
$input.removeClass('invalid');
|
||||
} else if (!isValidLength && !inputHasInvalidClass) {
|
||||
|
||||
$input.removeClass('valid');
|
||||
$input.addClass('invalid');
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
$('input, textarea').characterCounter();
|
||||
});
|
||||
})(jQuery);
|
||||
File diff suppressed because it is too large
Load Diff
Executable
+360
@@ -0,0 +1,360 @@
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
$(document).on('click', '.chip .close', function () {
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
if ($this.closest('.chips').data('initialized')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this.closest('.chip').remove();
|
||||
});
|
||||
});
|
||||
|
||||
$.fn.materialChip = function (options) {
|
||||
var _this = this;
|
||||
|
||||
this.$el = $(this);
|
||||
this.$document = $(document);
|
||||
|
||||
this.eventsHandled = false;
|
||||
|
||||
this.defaultOptions = {
|
||||
data: [],
|
||||
placeholder: '',
|
||||
secondaryPlaceholder: ''
|
||||
};
|
||||
|
||||
this.selectors = {
|
||||
chips: '.chips',
|
||||
chip: '.chip',
|
||||
input: 'input',
|
||||
delete: '.fa',
|
||||
selectedChip: '.selected'
|
||||
};
|
||||
|
||||
this.keyCodes = {
|
||||
enter: 13,
|
||||
backspace: 8,
|
||||
delete: 46,
|
||||
arrowLeft: 37,
|
||||
arrowRight: 39
|
||||
};
|
||||
|
||||
if (options === 'data') {
|
||||
return this.$el.data('chips');
|
||||
}
|
||||
|
||||
if (options === 'options') {
|
||||
return this.$el.data('options');
|
||||
}
|
||||
|
||||
this.$el.data('options', $.extend({}, this.defaultOptions, options));
|
||||
|
||||
this.init = function () {
|
||||
|
||||
_this.$el.each(function (index, element) {
|
||||
|
||||
var $this = $(element);
|
||||
if ($this.data('initialized')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var options = $this.data('options');
|
||||
if (!options.data || !Array.isArray(options.data)) {
|
||||
options.data = [];
|
||||
}
|
||||
|
||||
$this.data('chips', options.data);
|
||||
$this.data('index', index);
|
||||
$this.data('initialized', true);
|
||||
|
||||
if (!$this.hasClass(_this.selectors.chips)) {
|
||||
$this.addClass('chips');
|
||||
}
|
||||
|
||||
_this.renderChips($this);
|
||||
});
|
||||
};
|
||||
|
||||
this.handleEvents = function () {
|
||||
var _this2 = this;
|
||||
|
||||
this.$document.on('click', this.selectors.chips, function (e) {
|
||||
|
||||
$(e.target).find(_this2.selectors.input).focus();
|
||||
});
|
||||
|
||||
this.$document.on('click', this.selectors.chip, function (e) {
|
||||
|
||||
$(_this2.selectors.chip).removeClass('selected');
|
||||
$(e.target).addClass('selected');
|
||||
});
|
||||
|
||||
this.$document.on('keydown', function (e) {
|
||||
|
||||
if ($(e.target).is('input, textarea')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $selectedChip = _this2.$document.find(_this2.selectors.chip + _this2.selectors.selectedChip);
|
||||
var $chipsWrapper = $selectedChip.closest(_this2.selectors.chips);
|
||||
var siblingsLength = $selectedChip.siblings(_this2.selectors.chip).length;
|
||||
|
||||
if (!$selectedChip.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var backspacePressed = e.which === _this2.keyCodes.backspace;
|
||||
var deletePressed = e.which === _this2.keyCodes.delete;
|
||||
var leftArrowPressed = e.which === _this2.keyCodes.arrowLeft;
|
||||
var rightArrowPressed = e.which === _this2.keyCodes.arrowRight;
|
||||
|
||||
if (backspacePressed || deletePressed) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
_this2.deleteSelectedChip($chipsWrapper, $selectedChip, siblingsLength);
|
||||
} else if (leftArrowPressed) {
|
||||
|
||||
_this2.selectLeftChip($chipsWrapper, $selectedChip);
|
||||
} else if (rightArrowPressed) {
|
||||
|
||||
_this2.selectRightChip($chipsWrapper, $selectedChip, siblingsLength);
|
||||
}
|
||||
});
|
||||
|
||||
this.$document.on('focusin', this.selectors.chips + ' ' + this.selectors.input, function (e) {
|
||||
|
||||
$(e.target).closest(_this2.selectors.chips).addClass('focus');
|
||||
$(_this2.selectors.chip).removeClass('selected');
|
||||
});
|
||||
|
||||
this.$document.on('focusout', this.selectors.chips + ' ' + this.selectors.input, function (e) {
|
||||
|
||||
$(e.target).closest(_this2.selectors.chips).removeClass('focus');
|
||||
});
|
||||
|
||||
this.$document.on('keydown', this.selectors.chips + ' ' + this.selectors.input, function (e) {
|
||||
|
||||
var $target = $(e.target);
|
||||
var $chipsWrapper = $target.closest(_this2.selectors.chips);
|
||||
var chipsIndex = $chipsWrapper.data('index');
|
||||
var chipsLength = $chipsWrapper.children(_this2.selectors.chip).length;
|
||||
|
||||
var enterPressed = e.which === _this2.keyCodes.enter;
|
||||
|
||||
if (enterPressed) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
_this2.addChip(chipsIndex, {
|
||||
tag: $target.val()
|
||||
}, $chipsWrapper);
|
||||
|
||||
$target.val('');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var leftArrowOrDeletePressed = e.keyCode === _this2.keyCodes.arrowLeft || e.keyCode === _this2.keyCodes.delete;
|
||||
var isValueEmpty = $target.val() === '';
|
||||
|
||||
if (leftArrowOrDeletePressed && isValueEmpty && chipsLength) {
|
||||
|
||||
_this2.selectChip(chipsIndex, chipsLength - 1, $chipsWrapper);
|
||||
|
||||
$target.blur();
|
||||
}
|
||||
});
|
||||
|
||||
this.$document.on('click', this.selectors.chips + ' ' + this.selectors.delete, function (e) {
|
||||
|
||||
var $target = $(e.target);
|
||||
var $chipsWrapper = $target.closest(_this2.selectors.chips);
|
||||
var $chip = $target.closest(_this2.selectors.chip);
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
_this2.deleteChip($chipsWrapper.data('index'), $chip.index(), $chipsWrapper);
|
||||
|
||||
$chipsWrapper.find('input').focus();
|
||||
});
|
||||
};
|
||||
|
||||
this.deleteSelectedChip = function ($chipsWrapper, $selectedChip, siblingsLength) {
|
||||
|
||||
var chipsIndex = $chipsWrapper.data('index');
|
||||
var chipIndex = $selectedChip.index();
|
||||
_this.deleteChip(chipsIndex, chipIndex, $chipsWrapper);
|
||||
|
||||
var selectIndex = null;
|
||||
|
||||
if (chipIndex < siblingsLength - 1) {
|
||||
selectIndex = chipIndex;
|
||||
} else if (chipIndex === siblingsLength || chipIndex === siblingsLength - 1) {
|
||||
selectIndex = siblingsLength - 1;
|
||||
}
|
||||
|
||||
if (selectIndex < 0) {
|
||||
selectIndex = null;
|
||||
}
|
||||
|
||||
if (selectIndex !== null) {
|
||||
_this.selectChip(chipsIndex, selectIndex, $chipsWrapper);
|
||||
}
|
||||
|
||||
if (!siblingsLength) {
|
||||
$chipsWrapper.find('input').focus();
|
||||
}
|
||||
};
|
||||
|
||||
this.selectLeftChip = function ($chipsWrapper, $selectedChip) {
|
||||
|
||||
var chipIndex = $selectedChip.index() - 1;
|
||||
if (chipIndex < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(_this.selectors.chip).removeClass('selected');
|
||||
|
||||
_this.selectChip($chipsWrapper.data('index'), chipIndex, $chipsWrapper);
|
||||
};
|
||||
|
||||
this.selectRightChip = function ($chipsWrapper, $selectedChip, siblingsLength) {
|
||||
|
||||
var chipIndex = $selectedChip.index() + 1;
|
||||
$(_this.selectors.chip).removeClass('selected');
|
||||
if (chipIndex > siblingsLength) {
|
||||
|
||||
$chipsWrapper.find('input').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
_this.selectChip($chipsWrapper.data('index'), chipIndex, $chipsWrapper);
|
||||
};
|
||||
|
||||
this.renderChips = function ($chipsWrapper) {
|
||||
|
||||
var html = '';
|
||||
|
||||
$chipsWrapper.data('chips').forEach(function (elem) {
|
||||
|
||||
html += _this.getSingleChipHtml(elem);
|
||||
});
|
||||
|
||||
html += '<input class="input" placeholder="">';
|
||||
|
||||
$chipsWrapper.html(html);
|
||||
|
||||
_this.setPlaceholder($chipsWrapper);
|
||||
};
|
||||
|
||||
this.getSingleChipHtml = function (elem) {
|
||||
|
||||
if (!elem.tag) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var html = '<div class="chip">' + elem.tag;
|
||||
|
||||
if (elem.image) {
|
||||
html += ' <img src="' + elem.image + '"> ';
|
||||
}
|
||||
|
||||
html += '<i class="close fa fa-times"></i>';
|
||||
html += '</div>';
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
this.setPlaceholder = function ($chips) {
|
||||
|
||||
var options = $chips.data('options');
|
||||
|
||||
if ($chips.data('chips').length && options.placeholder) {
|
||||
|
||||
$chips.find('input').prop('placeholder', options.placeholder);
|
||||
} else if (!$chips.data('chips').length && options.secondaryPlaceholder) {
|
||||
|
||||
$chips.find('input').prop('placeholder', options.secondaryPlaceholder);
|
||||
}
|
||||
};
|
||||
|
||||
this.isValid = function ($chipsWrapper, elem) {
|
||||
|
||||
var chips = $chipsWrapper.data('chips');
|
||||
|
||||
for (var i = 0; i < chips.length; i++) {
|
||||
|
||||
if (chips[i].tag === elem.tag) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return elem.tag !== '';
|
||||
};
|
||||
|
||||
this.addChip = function (chipsIndex, elem, $chipsWrapper) {
|
||||
|
||||
if (!_this.isValid($chipsWrapper, elem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var chipHtml = _this.getSingleChipHtml(elem);
|
||||
|
||||
$chipsWrapper.data('chips').push(elem);
|
||||
|
||||
$(chipHtml).insertBefore($chipsWrapper.find('input'));
|
||||
|
||||
$chipsWrapper.trigger('chip.add', elem);
|
||||
|
||||
_this.setPlaceholder($chipsWrapper);
|
||||
};
|
||||
|
||||
this.deleteChip = function (chipsIndex, chipIndex, $chipsWrapper) {
|
||||
|
||||
var chip = $chipsWrapper.data('chips')[chipIndex];
|
||||
|
||||
$chipsWrapper.find('.chip').eq(chipIndex).remove();
|
||||
$chipsWrapper.data('chips').splice(chipIndex, 1);
|
||||
$chipsWrapper.trigger('chip.delete', chip);
|
||||
|
||||
_this.setPlaceholder($chipsWrapper);
|
||||
};
|
||||
|
||||
this.selectChip = function (chipsIndex, chipIndex, $chipsWrapper) {
|
||||
|
||||
var $chip = $chipsWrapper.find('.chip').eq(chipIndex);
|
||||
|
||||
if ($chip && $chip.hasClass('selected') === false) {
|
||||
|
||||
$chip.addClass('selected');
|
||||
$chipsWrapper.trigger('chip.select', $chipsWrapper.data('chips')[chipIndex]);
|
||||
}
|
||||
};
|
||||
|
||||
this.getChipsElement = function (index, $chipsWrapper) {
|
||||
return $chipsWrapper.eq(index);
|
||||
};
|
||||
|
||||
this.init();
|
||||
|
||||
if (!this.eventsHandled) {
|
||||
|
||||
this.handleEvents();
|
||||
this.eventsHandled = true;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// Deprecated. To be deleted in future releases
|
||||
$.fn.material_chip = $.fn.materialChip;
|
||||
})(jQuery);
|
||||
Executable
+156
@@ -0,0 +1,156 @@
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
|
||||
$.fn.collapsible = function (options) {
|
||||
|
||||
var defaults = {
|
||||
accordion: undefined
|
||||
};
|
||||
|
||||
options = $.extend(defaults, options);
|
||||
|
||||
function accordionOpen($collapsible, object) {
|
||||
|
||||
$panelHeaders = $collapsible.find('> li > .collapsible-header');
|
||||
if (object.hasClass('active')) {
|
||||
|
||||
object.parent().addClass('active');
|
||||
} else {
|
||||
|
||||
object.parent().removeClass('active');
|
||||
}
|
||||
|
||||
if (object.parent().hasClass('active')) {
|
||||
|
||||
object.siblings('.collapsible-body').stop(true, false).slideDown({
|
||||
duration: 350,
|
||||
easing: 'easeOutQuart',
|
||||
queue: false,
|
||||
complete: function complete() {
|
||||
|
||||
$(this).css('height', '');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
object.siblings('.collapsible-body').stop(true, false).slideUp({
|
||||
duration: 350,
|
||||
easing: 'easeOutQuart',
|
||||
queue: false,
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$panelHeaders.not(object).removeClass('active').parent().removeClass('active');
|
||||
$panelHeaders.not(object).parent().children('.collapsible-body').stop(true, false).slideUp({
|
||||
duration: 350,
|
||||
easing: 'easeOutQuart',
|
||||
queue: false,
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function expandableOpen(object) {
|
||||
|
||||
if (object.hasClass('active')) {
|
||||
|
||||
object.parent().addClass('active');
|
||||
} else {
|
||||
|
||||
object.parent().removeClass('active');
|
||||
}
|
||||
|
||||
if (object.parent().hasClass('active')) {
|
||||
|
||||
object.siblings('.collapsible-body').stop(true, false).slideDown({
|
||||
duration: 350,
|
||||
easing: 'easeOutQuart',
|
||||
queue: false,
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
object.siblings('.collapsible-body').stop(true, false).slideUp({
|
||||
duration: 350,
|
||||
easing: 'easeOutQuart',
|
||||
queue: false,
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function isChildrenOfPanelHeader(object) {
|
||||
|
||||
var panelHeader = getPanelHeader(object);
|
||||
return panelHeader.length > 0;
|
||||
}
|
||||
|
||||
function getPanelHeader(object) {
|
||||
|
||||
return object.closest('li > .collapsible-header');
|
||||
}
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
var $panelHeaders = $(this).find('> li > .collapsible-header');
|
||||
|
||||
var collapsibleType = $this.data('collapsible');
|
||||
|
||||
// Turn off any existing event handlers
|
||||
$this.off('click.collapse', '.collapsible-header');
|
||||
$panelHeaders.off('click.collapse');
|
||||
|
||||
if (options.accordion || collapsibleType === 'accordion' || collapsibleType === undefined) {
|
||||
|
||||
$panelHeaders = $this.find('> li > .collapsible-header');
|
||||
$panelHeaders.on('click.collapse', function (e) {
|
||||
|
||||
var element = $(e.target);
|
||||
|
||||
if (isChildrenOfPanelHeader(element)) {
|
||||
|
||||
element = getPanelHeader(element);
|
||||
}
|
||||
|
||||
element.toggleClass('active');
|
||||
accordionOpen($this, element);
|
||||
});
|
||||
|
||||
accordionOpen($this, $panelHeaders.filter('.active').first());
|
||||
} else {
|
||||
|
||||
$panelHeaders.each(function () {
|
||||
|
||||
$(this).on('click.collapse', function (e) {
|
||||
|
||||
var element = $(e.target);
|
||||
if (isChildrenOfPanelHeader(element)) {
|
||||
|
||||
element = getPanelHeader(element);
|
||||
}
|
||||
element.toggleClass('active');
|
||||
expandableOpen(element);
|
||||
});
|
||||
|
||||
if ($(this).hasClass('active')) {
|
||||
|
||||
expandableOpen($(this));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('.collapsible').collapsible();
|
||||
})(jQuery);
|
||||
Executable
+357
@@ -0,0 +1,357 @@
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
|
||||
$.fn.scrollTo = function (elem) {
|
||||
|
||||
$(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem).offset().top);
|
||||
return this;
|
||||
};
|
||||
|
||||
$.fn.dropdown = function (option) {
|
||||
|
||||
this.each(function () {
|
||||
|
||||
var origin = $(this);
|
||||
var options = $.extend({}, $.fn.dropdown.defaults, option);
|
||||
var isFocused = false;
|
||||
|
||||
// Dropdown menu
|
||||
var activates = $('#' + origin.attr('data-activates'));
|
||||
|
||||
function updateOptions() {
|
||||
|
||||
if (origin.data('induration') !== undefined) {
|
||||
options.inDuration = origin.data('inDuration');
|
||||
}
|
||||
if (origin.data('outduration') !== undefined) {
|
||||
options.outDuration = origin.data('outDuration');
|
||||
}
|
||||
if (origin.data('constrainwidth') !== undefined) {
|
||||
options.constrain_width = origin.data('constrainwidth');
|
||||
}
|
||||
if (origin.data('hover') !== undefined) {
|
||||
options.hover = origin.data('hover');
|
||||
}
|
||||
if (origin.data('gutter') !== undefined) {
|
||||
options.gutter = origin.data('gutter');
|
||||
}
|
||||
if (origin.data('beloworigin') !== undefined) {
|
||||
options.belowOrigin = origin.data('beloworigin');
|
||||
}
|
||||
if (origin.data('alignment') !== undefined) {
|
||||
options.alignment = origin.data('alignment');
|
||||
}
|
||||
}
|
||||
|
||||
updateOptions();
|
||||
|
||||
// Attach dropdown to its activator
|
||||
origin.after(activates);
|
||||
|
||||
/*
|
||||
Helper function to position and resize dropdown.
|
||||
Used in hover and click handler.
|
||||
*/
|
||||
function placeDropdown(eventType) {
|
||||
|
||||
// Check for simultaneous focus and click events.
|
||||
if (eventType === 'focus') {
|
||||
isFocused = true;
|
||||
}
|
||||
|
||||
// Check html data attributes
|
||||
updateOptions();
|
||||
|
||||
// Set Dropdown state
|
||||
activates.addClass('active');
|
||||
origin.addClass('active');
|
||||
|
||||
// Constrain width
|
||||
if (options.constrain_width === true) {
|
||||
|
||||
activates.css('width', origin.outerWidth());
|
||||
} else {
|
||||
|
||||
activates.css('white-space', 'nowrap');
|
||||
}
|
||||
|
||||
// Offscreen detection
|
||||
var windowHeight = window.innerHeight;
|
||||
var originHeight = origin.innerHeight();
|
||||
var offsetLeft = origin.offset().left;
|
||||
var offsetTop = origin.offset().top - $(window).scrollTop();
|
||||
var currAlignment = options.alignment;
|
||||
var gutterSpacing = 0;
|
||||
var leftPosition = 0;
|
||||
|
||||
// Below Origin
|
||||
var verticalOffset = 0;
|
||||
if (options.belowOrigin === true) {
|
||||
verticalOffset = originHeight;
|
||||
}
|
||||
|
||||
// Check for scrolling positioned container.
|
||||
var scrollOffset = 0;
|
||||
var wrapper = origin.parent();
|
||||
if (!wrapper.is('body') && wrapper[0].scrollHeight > wrapper[0].clientHeight) {
|
||||
|
||||
scrollOffset = wrapper[0].scrollTop;
|
||||
}
|
||||
|
||||
if (offsetLeft + activates.innerWidth() > $(window).width()) {
|
||||
|
||||
// Dropdown goes past screen on right, force right alignment
|
||||
currAlignment = 'right';
|
||||
} else if (offsetLeft - activates.innerWidth() + origin.innerWidth() < 0) {
|
||||
|
||||
// Dropdown goes past screen on left, force left alignment
|
||||
currAlignment = 'left';
|
||||
}
|
||||
// Vertical bottom offscreen detection
|
||||
if (offsetTop + activates.innerHeight() > windowHeight) {
|
||||
|
||||
// If going upwards still goes offscreen, just crop height of dropdown.
|
||||
if (offsetTop + originHeight - activates.innerHeight() < 0) {
|
||||
|
||||
var adjustedHeight = windowHeight - offsetTop - verticalOffset;
|
||||
activates.css('max-height', adjustedHeight);
|
||||
} else {
|
||||
|
||||
// Flow upwards.
|
||||
if (!verticalOffset) {
|
||||
verticalOffset += originHeight;
|
||||
}
|
||||
verticalOffset -= activates.innerHeight();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle edge alignment
|
||||
if (currAlignment === 'left') {
|
||||
|
||||
gutterSpacing = options.gutter;
|
||||
leftPosition = origin.position().left + gutterSpacing;
|
||||
} else if (currAlignment === 'right') {
|
||||
|
||||
var offsetRight = origin.position().left + origin.outerWidth() - activates.outerWidth();
|
||||
gutterSpacing = -options.gutter;
|
||||
leftPosition = offsetRight + gutterSpacing;
|
||||
}
|
||||
|
||||
// Position dropdown
|
||||
activates.css({
|
||||
position: 'absolute',
|
||||
top: origin.position().top + verticalOffset + scrollOffset,
|
||||
left: leftPosition
|
||||
});
|
||||
|
||||
// Show dropdown
|
||||
activates.stop(true, true).css('opacity', 0).slideDown({
|
||||
queue: false,
|
||||
duration: options.inDuration,
|
||||
easing: 'easeOutCubic',
|
||||
complete: function complete() {
|
||||
$(this).css('height', '');
|
||||
}
|
||||
}).animate({
|
||||
opacity: 1,
|
||||
scrollTop: 0
|
||||
}, {
|
||||
queue: false,
|
||||
duration: options.inDuration,
|
||||
easing: 'easeOutSine'
|
||||
});
|
||||
}
|
||||
|
||||
function hideDropdown() {
|
||||
|
||||
// Check for simultaneous focus and click events.
|
||||
isFocused = false;
|
||||
activates.fadeOut(options.outDuration);
|
||||
activates.removeClass('active');
|
||||
origin.removeClass('active');
|
||||
setTimeout(function () {
|
||||
activates.css('max-height', '');
|
||||
}, options.outDuration);
|
||||
}
|
||||
|
||||
// Hover
|
||||
if (options.hover) {
|
||||
|
||||
var open = false;
|
||||
origin.unbind('click.' + origin.attr('id'));
|
||||
// Hover handler to show dropdown
|
||||
origin.on('mouseenter', function () {
|
||||
// Mouse over
|
||||
|
||||
if (open === false) {
|
||||
|
||||
placeDropdown();
|
||||
open = true;
|
||||
}
|
||||
});
|
||||
origin.on('mouseleave', function (e) {
|
||||
|
||||
// If hover on origin then to something other than dropdown content, then close
|
||||
var toEl = e.toElement || e.relatedTarget; // added browser compatibility for target element
|
||||
if (!$(toEl).closest('.dropdown-content').is(activates)) {
|
||||
|
||||
activates.stop(true, true);
|
||||
hideDropdown();
|
||||
open = false;
|
||||
}
|
||||
});
|
||||
|
||||
activates.on('mouseleave', function (e) {
|
||||
// Mouse out
|
||||
|
||||
var toEl = e.toElement || e.relatedTarget;
|
||||
if (!$(toEl).closest('.dropdown-button').is(origin)) {
|
||||
|
||||
activates.stop(true, true);
|
||||
hideDropdown();
|
||||
open = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Click
|
||||
} else {
|
||||
|
||||
// Click handler to show dropdown
|
||||
origin.unbind('click.' + origin.attr('id'));
|
||||
origin.bind('click.' + origin.attr('id'), function (e) {
|
||||
|
||||
if (!isFocused) {
|
||||
|
||||
if (origin[0] === e.currentTarget && !origin.hasClass('active') && $(e.target).closest('.dropdown-content').length === 0) {
|
||||
|
||||
e.preventDefault(); // Prevents button click from moving window
|
||||
placeDropdown('click');
|
||||
} else if (origin.hasClass('active')) {
|
||||
// If origin is clicked and menu is open, close menu
|
||||
|
||||
hideDropdown();
|
||||
$(document).unbind('click.' + activates.attr('id') + ' touchstart.' + activates.attr('id'));
|
||||
}
|
||||
// If menu open, add click close handler to document
|
||||
if (activates.hasClass('active')) {
|
||||
|
||||
$(document).bind('click.' + activates.attr('id') + ' touchstart.' + activates.attr('id'), function (e) {
|
||||
|
||||
if (!activates.is(e.target) && !origin.is(e.target) && !origin.find(e.target).length) {
|
||||
|
||||
hideDropdown();
|
||||
$(document).unbind('click.' + activates.attr('id') + ' touchstart.' + activates.attr('id'));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
origin.on('open', function (e, eventType) {
|
||||
|
||||
placeDropdown(eventType);
|
||||
});
|
||||
|
||||
origin.on('close', hideDropdown);
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.dropdown.defaults = {
|
||||
inDuration: 300,
|
||||
outDuration: 225,
|
||||
constrain_width: true,
|
||||
hover: false,
|
||||
gutter: 0,
|
||||
belowOrigin: false,
|
||||
alignment: 'left'
|
||||
};
|
||||
|
||||
$('.dropdown-button').dropdown();
|
||||
})(jQuery);
|
||||
|
||||
var dropdownSelectors = $('.dropdown, .dropup');
|
||||
|
||||
// Custom function to read dropdown data
|
||||
function dropdownEffectData(target) {
|
||||
|
||||
// TODO - page level global?
|
||||
var effectInDefault = 'fadeIn';
|
||||
var effectOutDefault = 'fadeOut';
|
||||
var dropdown = $(target);
|
||||
var dropdownMenu = $('.dropdown-menu', target);
|
||||
var parentUl = dropdown.parents('ul.nav');
|
||||
|
||||
// If parent is ul.nav allow global effect settings
|
||||
if (parentUl.height > 0) {
|
||||
|
||||
effectInDefault = parentUl.data('dropdown-in') || null;
|
||||
effectOutDefault = parentUl.data('dropdown-out') || null;
|
||||
}
|
||||
|
||||
return {
|
||||
target: target,
|
||||
dropdown: dropdown,
|
||||
dropdownMenu: dropdownMenu,
|
||||
effectIn: dropdownMenu.data('dropdown-in') || effectInDefault,
|
||||
effectOut: dropdownMenu.data('dropdown-out') || effectOutDefault
|
||||
};
|
||||
}
|
||||
|
||||
// Custom function to start effect (in or out)
|
||||
function dropdownEffectStart(data, effectToStart) {
|
||||
|
||||
if (effectToStart) {
|
||||
|
||||
data.dropdown.addClass('dropdown-animating');
|
||||
data.dropdownMenu.addClass(['animated', effectToStart].join(' '));
|
||||
}
|
||||
}
|
||||
|
||||
// Custom function to read when animation is over
|
||||
function dropdownEffectEnd(data, callbackFunc) {
|
||||
|
||||
var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
|
||||
data.dropdown.one(animationEnd, function () {
|
||||
|
||||
data.dropdown.removeClass('dropdown-animating');
|
||||
data.dropdownMenu.removeClass(['animated', data.effectIn, data.effectOut].join(' '));
|
||||
|
||||
// Custom callback option, used to remove open class in out effect
|
||||
if (typeof callbackFunc === 'function') {
|
||||
|
||||
callbackFunc();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Bootstrap API hooks
|
||||
dropdownSelectors.on({
|
||||
'show.bs.dropdown': function showBsDropdown() {
|
||||
// On show, start in effect
|
||||
var dropdown = dropdownEffectData(this);
|
||||
dropdownEffectStart(dropdown, dropdown.effectIn);
|
||||
},
|
||||
'shown.bs.dropdown': function shownBsDropdown() {
|
||||
// On shown, remove in effect once complete
|
||||
var dropdown = dropdownEffectData(this);
|
||||
if (dropdown.effectIn && dropdown.effectOut) {
|
||||
dropdownEffectEnd(dropdown);
|
||||
}
|
||||
},
|
||||
'hide.bs.dropdown': function hideBsDropdown(e) {
|
||||
// On hide, start out effect
|
||||
var dropdown = dropdownEffectData(this);
|
||||
if (dropdown.effectOut) {
|
||||
|
||||
e.preventDefault();
|
||||
dropdownEffectStart(dropdown, dropdown.effectOut);
|
||||
dropdownEffectEnd(dropdown, function () {
|
||||
|
||||
dropdown.dropdown.removeClass('show');
|
||||
dropdown.dropdownMenu.removeClass('show');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Enhanced Bootstrap Modals
|
||||
https://mdbootstrap.com
|
||||
office@mdbootstrap.com
|
||||
*/
|
||||
|
||||
$('body').on('shown.bs.modal', '.modal', function() {
|
||||
if($('.modal-backdrop').length) {
|
||||
} else {
|
||||
|
||||
$modal_dialog = $(this).children('.modal-dialog')
|
||||
|
||||
if($modal_dialog.hasClass('modal-side')) {
|
||||
$(this).addClass('modal-scrolling');
|
||||
$('body').addClass('scrollable');
|
||||
}
|
||||
|
||||
if($modal_dialog.hasClass('modal-frame')) {
|
||||
$(this).addClass('modal-content-clickable');
|
||||
$('body').addClass('scrollable');
|
||||
}
|
||||
}
|
||||
});
|
||||
$('body').on('hidden.bs.modal', '.modal', function() {
|
||||
$('body').removeClass('scrollable');
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
/** *****************
|
||||
* File input *
|
||||
******************/
|
||||
(function ($) {
|
||||
|
||||
$(document).on('change', '.file-field input[type="file"]', function (e) {
|
||||
|
||||
var $this = $(e.target);
|
||||
var $file_field = $this.closest('.file-field');
|
||||
var $path_input = $file_field.find('input.file-path');
|
||||
var files = $this[0].files;
|
||||
var file_names = [];
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var file_name = files[i].name;
|
||||
file_names.push(file_name);
|
||||
}
|
||||
$path_input.val(file_names.join(', '));
|
||||
$path_input.trigger('change');
|
||||
});
|
||||
})(jQuery);
|
||||
Executable
+208
@@ -0,0 +1,208 @@
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
|
||||
var inputSelector = ['text', 'password', 'email', 'url', 'tel', 'number', 'search', 'search-md'].map(function (selector) {
|
||||
return 'input[type=' + selector + ']';
|
||||
}).join(', ') + ', textarea';
|
||||
|
||||
var textAreaSelector = '.materialize-textarea';
|
||||
|
||||
var updateTextFields = function updateTextFields($input) {
|
||||
|
||||
var $labelAndIcon = $input.siblings('label, i');
|
||||
var hasValue = $input.val().length;
|
||||
var hasPlaceholder = $input.attr('placeholder');
|
||||
var addOrRemove = (hasValue || hasPlaceholder ? 'add' : 'remove') + 'Class';
|
||||
|
||||
$labelAndIcon[addOrRemove]('active');
|
||||
};
|
||||
|
||||
var validateField = function validateField($input) {
|
||||
|
||||
if ($input.hasClass('validate')) {
|
||||
|
||||
var value = $input.val();
|
||||
var noValue = !value.length;
|
||||
var isValid = !$input[0].validity.badInput;
|
||||
|
||||
if (noValue && isValid) {
|
||||
|
||||
$input.removeClass('valid').removeClass('invalid');
|
||||
} else {
|
||||
|
||||
var valid = $input.is(':valid');
|
||||
var length = Number($input.attr('length')) || 0;
|
||||
|
||||
if (valid && (!length || length > value.length)) {
|
||||
|
||||
$input.removeClass('invalid').addClass('valid');
|
||||
} else {
|
||||
|
||||
$input.removeClass('valid').addClass('invalid');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var textAreaAutoResize = function textAreaAutoResize() {
|
||||
|
||||
var $textarea = $(undefined);
|
||||
if ($textarea.val().length) {
|
||||
|
||||
var $hiddenDiv = $('.hiddendiv');
|
||||
var fontFamily = $textarea.css('font-family');
|
||||
var fontSize = $textarea.css('font-size');
|
||||
|
||||
if (fontSize) {
|
||||
|
||||
$hiddenDiv.css('font-size', fontSize);
|
||||
}
|
||||
|
||||
if (fontFamily) {
|
||||
|
||||
$hiddenDiv.css('font-family', fontFamily);
|
||||
}
|
||||
|
||||
if ($textarea.attr('wrap') === 'off') {
|
||||
|
||||
$hiddenDiv.css('overflow-wrap', 'normal').css('white-space', 'pre');
|
||||
}
|
||||
|
||||
$hiddenDiv.text($textarea.val() + '\n');
|
||||
var content = $hiddenDiv.html().replace(/\n/g, '<br>');
|
||||
$hiddenDiv.html(content);
|
||||
|
||||
// When textarea is hidden, width goes crazy.
|
||||
// Approximate with half of window size
|
||||
$hiddenDiv.css('width', $textarea.is(':visible') ? $textarea.width() : $(window).width() / 2);
|
||||
$textarea.css('height', $hiddenDiv.height());
|
||||
}
|
||||
};
|
||||
|
||||
$(inputSelector).each(function (index, input) {
|
||||
|
||||
var $this = $(input);
|
||||
var $labelAndIcon = $this.siblings('label, i');
|
||||
updateTextFields($this);
|
||||
var isValid = input.validity.badInput;
|
||||
if (isValid) {
|
||||
|
||||
$labelAndIcon.addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('focus', inputSelector, function (e) {
|
||||
|
||||
$(e.target).siblings('label, i').addClass('active');
|
||||
});
|
||||
|
||||
$(document).on('blur', inputSelector, function (e) {
|
||||
|
||||
var $this = $(e.target);
|
||||
var noValue = !$this.val();
|
||||
var invalid = !e.target.validity.badInput;
|
||||
var noPlaceholder = $this.attr('placeholder') === undefined;
|
||||
|
||||
if (noValue && invalid && noPlaceholder) {
|
||||
|
||||
$this.siblings('label, i').removeClass('active');
|
||||
}
|
||||
|
||||
validateField($this);
|
||||
});
|
||||
|
||||
$(document).on('change', inputSelector, function (e) {
|
||||
|
||||
var $this = $(e.target);
|
||||
updateTextFields($this);
|
||||
validateField($this);
|
||||
});
|
||||
|
||||
$('input[autofocus]').siblings('label, i').addClass('active');
|
||||
|
||||
$(document).on('reset', function (e) {
|
||||
|
||||
var $formReset = $(e.target);
|
||||
if ($formReset.is('form')) {
|
||||
|
||||
var $formInputs = $formReset.find(inputSelector);
|
||||
$formInputs.removeClass('valid').removeClass('invalid').each(function (index, input) {
|
||||
|
||||
var $this = $(input);
|
||||
var noDefaultValue = !$this.val();
|
||||
var noPlaceholder = !$this.attr('placeholder');
|
||||
if (noDefaultValue && noPlaceholder) {
|
||||
$this.siblings('label, i').removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
$formReset.find('select.initialized').each(function (index, select) {
|
||||
|
||||
var $select = $(select);
|
||||
var $visibleInput = $select.siblings('input.select-dropdown');
|
||||
var defaultValue = $select.children('[selected]').val();
|
||||
|
||||
$select.val(defaultValue);
|
||||
$visibleInput.val(defaultValue);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function init() {
|
||||
|
||||
var $text = $('.md-textarea-auto');
|
||||
if ($text.length) {
|
||||
|
||||
var observe = void 0;
|
||||
if (window.attachEvent) {
|
||||
|
||||
observe = function observe(element, event, handler) {
|
||||
|
||||
element.attachEvent('on' + event, handler);
|
||||
};
|
||||
} else {
|
||||
|
||||
observe = function observe(element, event, handler) {
|
||||
|
||||
element.addEventListener(event, handler, false);
|
||||
};
|
||||
}
|
||||
|
||||
$text.each(function () {
|
||||
|
||||
var self = this;
|
||||
|
||||
function resize() {
|
||||
|
||||
self.style.height = 'auto';
|
||||
self.style.height = self.scrollHeight + 'px';
|
||||
}
|
||||
|
||||
function delayedResize() {
|
||||
|
||||
window.setTimeout(resize, 0);
|
||||
}
|
||||
|
||||
observe(self, 'change', resize);
|
||||
observe(self, 'cut', delayedResize);
|
||||
observe(self, 'paste', delayedResize);
|
||||
observe(self, 'drop', delayedResize);
|
||||
observe(self, 'keydown', delayedResize);
|
||||
|
||||
resize();
|
||||
});
|
||||
}
|
||||
}
|
||||
init();
|
||||
|
||||
var $body = $('body');
|
||||
if (!$('.hiddendiv').first().length) {
|
||||
|
||||
var $hiddenDiv = $('<div class="hiddendiv common"></div>');
|
||||
$body.append($hiddenDiv);
|
||||
}
|
||||
|
||||
$(textAreaSelector).each(textAreaAutoResize);
|
||||
$body.on('keyup keydown', textAreaSelector, textAreaAutoResize);
|
||||
})(jQuery);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,127 @@
|
||||
|
||||
## Reporting Bugs
|
||||
|
||||
Each bug report MUST have a [JSFiddle/JSBin] recreation before any work can begin. [further instructions »](http://fullcalendar.io/wiki/Reporting-Bugs/)
|
||||
|
||||
|
||||
## Requesting Features
|
||||
|
||||
Please search the [Issue Tracker] to see if your feature has already been requested, and if so, subscribe to it. Otherwise, read these [further instructions »](http://fullcalendar.io/wiki/Requesting-Features/)
|
||||
|
||||
|
||||
## Contributing Features
|
||||
|
||||
The FullCalendar project welcomes [Pull Requests][Using Pull Requests] for new features, but because there are so many feature requests (over 100), and because every new feature requires refinement and maintenance, each PR will be prioritized against the project's other demands and might take a while to make it to an official release.
|
||||
|
||||
Furthermore, each new feature should be designed as robustly as possible and be useful beyond the immediate usecase it was initially designed for. Feel free to start a ticket discussing the feature's specs before coding.
|
||||
|
||||
|
||||
## Contributing Bugfixes
|
||||
|
||||
In the description of your [Pull Request][Using Pull Requests], please include recreation steps for the bug as well as a [JSFiddle/JSBin] demo. Communicating the buggy behavior is a requirement before a merge can happen.
|
||||
|
||||
|
||||
## Contributing Locales
|
||||
|
||||
Please edit the original files in the `locale/` directory. DO NOT edit anything in the `dist/` directory. The build system will responsible for merging FullCalendar's `locale/` data with the [MomentJS locale data].
|
||||
|
||||
|
||||
## Other Ways to Contribute
|
||||
|
||||
[Read about other ways to contribute »](http://fullcalendar.io/wiki/Contributing/)
|
||||
|
||||
|
||||
## Getting Set Up
|
||||
|
||||
You will need [Git][git], [Node][node], and NPM installed. For clarification, please view the [jQuery readme][jq-readme], which requires a similar setup.
|
||||
|
||||
Also, you will need the [gulp-cli][gulp-cli] package installed globally (`-g`) on your system:
|
||||
|
||||
npm install -g gulp-cli
|
||||
|
||||
Then, clone FullCalendar's git repo:
|
||||
|
||||
git clone git://github.com/fullcalendar/fullcalendar.git
|
||||
|
||||
Enter the directory and install FullCalendar's dependencies:
|
||||
|
||||
cd fullcalendar
|
||||
npm install
|
||||
|
||||
|
||||
## What to edit
|
||||
|
||||
When modifying files, please do not edit the generated or minified files in the `dist/` directory. Please edit the original `src/` files.
|
||||
|
||||
|
||||
## Development Workflow
|
||||
|
||||
After you make code changes, you'll want to compile the JS/CSS so that it can be previewed from the tests and demos. You can either manually rebuild each time you make a change:
|
||||
|
||||
gulp dev
|
||||
|
||||
Or, you can run a script that automatically rebuilds whenever you save a source file:
|
||||
|
||||
gulp watch
|
||||
|
||||
When you are finished, run the following command to write the distributable files into the `./dist/` directory:
|
||||
|
||||
gulp dist
|
||||
|
||||
If you want to clean up the generated files, run:
|
||||
|
||||
gulp clean
|
||||
|
||||
|
||||
## Style Guide
|
||||
|
||||
Please follow the [Google JavaScript Style Guide] as closely as possible. With the following exceptions:
|
||||
|
||||
```js
|
||||
if (true) {
|
||||
}
|
||||
else { // please put else, else if, and catch on a separate line
|
||||
}
|
||||
|
||||
// please write one-line array literals with a one-space padding inside
|
||||
var a = [ 1, 2, 3 ];
|
||||
|
||||
// please write one-line object literals with a one-space padding inside
|
||||
var o = { a: 1, b: 2, c: 3 };
|
||||
```
|
||||
|
||||
Other exceptions:
|
||||
|
||||
- please ignore anything about Google Closure Compiler or the `goog` library
|
||||
- please do not write JSDoc comments
|
||||
|
||||
Notes about whitespace:
|
||||
|
||||
- **use *tabs* instead of spaces**
|
||||
- separate functions with *2* blank lines
|
||||
- separate logical blocks within functions with *1* blank line
|
||||
|
||||
Run the command line tool to automatically check your style:
|
||||
|
||||
gulp lint
|
||||
|
||||
|
||||
## Before Submitting your Code
|
||||
|
||||
If you have edited code (including **tests** and **translations**) and would like to submit a pull request, please make sure you have done the following:
|
||||
|
||||
1. Conformed to the style guide (successfully run `gulp lint`)
|
||||
|
||||
2. Written automated tests. View the [Automated Test Readme]
|
||||
|
||||
|
||||
[JSFiddle/JSBin]: http://fullcalendar.io/wiki/Reporting-Bugs/
|
||||
[Issue Tracker]: https://github.com/fullcalendar/fullcalendar/issues
|
||||
[Using Pull Requests]: https://help.github.com/articles/using-pull-requests/
|
||||
[MomentJS locale data]: https://github.com/moment/moment/tree/develop/locale
|
||||
[git]: http://git-scm.com/
|
||||
[node]: http://nodejs.org/
|
||||
[gulp-cli]: https://github.com/gulpjs/gulp/blob/master/docs/getting-started.md
|
||||
[jq-readme]: https://github.com/jquery/jquery/blob/master/README.md#what-you-need-to-build-your-own-jquery
|
||||
[Google JavaScript Style Guide]: http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
|
||||
[Automated Test Readme]: https://github.com/fullcalendar/fullcalendar/wiki/Automated-Tests
|
||||
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2015 Adam Shaw
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,106 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay,listWeek'
|
||||
},
|
||||
defaultDate: '2017-05-12',
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
editable: true,
|
||||
eventLimit: true, // allow "more" link when too many events
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
start: '2017-05-01'
|
||||
},
|
||||
{
|
||||
title: 'Long Event',
|
||||
start: '2017-05-07',
|
||||
end: '2017-05-10'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-09T16:00:00'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-16T16:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Conference',
|
||||
start: '2017-05-11',
|
||||
end: '2017-05-13'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T10:30:00',
|
||||
end: '2017-05-12T12:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Lunch',
|
||||
start: '2017-05-12T12:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T14:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Happy Hour',
|
||||
start: '2017-05-12T17:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Dinner',
|
||||
start: '2017-05-12T20:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Birthday Party',
|
||||
start: '2017-05-13T07:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Click for Google',
|
||||
url: 'http://google.com/',
|
||||
start: '2017-05-28'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 40px 10px;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay,listMonth'
|
||||
},
|
||||
defaultDate: '2017-05-12',
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
businessHours: true, // display business hours
|
||||
editable: true,
|
||||
events: [
|
||||
{
|
||||
title: 'Business Lunch',
|
||||
start: '2017-05-03T13:00:00',
|
||||
constraint: 'businessHours'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-13T11:00:00',
|
||||
constraint: 'availableForMeeting', // defined below
|
||||
color: '#257e4a'
|
||||
},
|
||||
{
|
||||
title: 'Conference',
|
||||
start: '2017-05-18',
|
||||
end: '2017-05-20'
|
||||
},
|
||||
{
|
||||
title: 'Party',
|
||||
start: '2017-05-29T20:00:00'
|
||||
},
|
||||
|
||||
// areas where "Meeting" must be dropped
|
||||
{
|
||||
id: 'availableForMeeting',
|
||||
start: '2017-05-11T10:00:00',
|
||||
end: '2017-05-11T16:00:00',
|
||||
rendering: 'background'
|
||||
},
|
||||
{
|
||||
id: 'availableForMeeting',
|
||||
start: '2017-05-13T10:00:00',
|
||||
end: '2017-05-13T16:00:00',
|
||||
rendering: 'background'
|
||||
},
|
||||
|
||||
// red areas where no events can be dropped
|
||||
{
|
||||
start: '2017-05-24',
|
||||
end: '2017-05-28',
|
||||
overlap: false,
|
||||
rendering: 'background',
|
||||
color: '#ff9f89'
|
||||
},
|
||||
{
|
||||
start: '2017-05-06',
|
||||
end: '2017-05-08',
|
||||
overlap: false,
|
||||
rendering: 'background',
|
||||
color: '#ff9f89'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 40px 10px;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,106 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,basicWeek,basicDay'
|
||||
},
|
||||
defaultDate: '2017-05-12',
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
editable: true,
|
||||
eventLimit: true, // allow "more" link when too many events
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
start: '2017-05-01'
|
||||
},
|
||||
{
|
||||
title: 'Long Event',
|
||||
start: '2017-05-07',
|
||||
end: '2017-05-10'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-09T16:00:00'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-16T16:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Conference',
|
||||
start: '2017-05-11',
|
||||
end: '2017-05-13'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T10:30:00',
|
||||
end: '2017-05-12T12:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Lunch',
|
||||
start: '2017-05-12T12:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T14:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Happy Hour',
|
||||
start: '2017-05-12T17:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Dinner',
|
||||
start: '2017-05-12T20:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Birthday Party',
|
||||
start: '2017-05-13T07:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Click for Google',
|
||||
url: 'http://google.com/',
|
||||
start: '2017-05-28'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 40px 10px;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,100 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
defaultDate: '2017-05-12',
|
||||
editable: true,
|
||||
eventLimit: true, // allow "more" link when too many events
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
start: '2017-05-01'
|
||||
},
|
||||
{
|
||||
title: 'Long Event',
|
||||
start: '2017-05-07',
|
||||
end: '2017-05-10'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-09T16:00:00'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-16T16:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Conference',
|
||||
start: '2017-05-11',
|
||||
end: '2017-05-13'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T10:30:00',
|
||||
end: '2017-05-12T12:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Lunch',
|
||||
start: '2017-05-12T12:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T14:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Happy Hour',
|
||||
start: '2017-05-12T17:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Dinner',
|
||||
start: '2017-05-12T20:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Birthday Party',
|
||||
start: '2017-05-13T07:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Click for Google',
|
||||
url: 'http://google.com/',
|
||||
start: '2017-05-28'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 40px 10px;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,135 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../lib/jquery-ui.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
|
||||
/* initialize the external events
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
$('#external-events .fc-event').each(function() {
|
||||
|
||||
// store data so the calendar knows to render an event upon drop
|
||||
$(this).data('event', {
|
||||
title: $.trim($(this).text()), // use the element's text as the event title
|
||||
stick: true // maintain when user navigates (see docs on the renderEvent method)
|
||||
});
|
||||
|
||||
// make the event draggable using jQuery UI
|
||||
$(this).draggable({
|
||||
zIndex: 999,
|
||||
revert: true, // will cause the event to go back to its
|
||||
revertDuration: 0 // original position after the drag
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
/* initialize the calendar
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay'
|
||||
},
|
||||
editable: true,
|
||||
droppable: true, // this allows things to be dropped onto the calendar
|
||||
drop: function() {
|
||||
// is the "remove after drop" checkbox checked?
|
||||
if ($('#drop-remove').is(':checked')) {
|
||||
// if so, remove the element from the "Draggable Events" list
|
||||
$(this).remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin-top: 40px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
}
|
||||
|
||||
#wrap {
|
||||
width: 1100px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#external-events {
|
||||
float: left;
|
||||
width: 150px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #ccc;
|
||||
background: #eee;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#external-events h4 {
|
||||
font-size: 16px;
|
||||
margin-top: 0;
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
#external-events .fc-event {
|
||||
margin: 10px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#external-events p {
|
||||
margin: 1.5em 0;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#external-events p input {
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
float: right;
|
||||
width: 900px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='wrap'>
|
||||
|
||||
<div id='external-events'>
|
||||
<h4>Draggable Events</h4>
|
||||
<div class='fc-event'>My Event 1</div>
|
||||
<div class='fc-event'>My Event 2</div>
|
||||
<div class='fc-event'>My Event 3</div>
|
||||
<div class='fc-event'>My Event 4</div>
|
||||
<div class='fc-event'>My Event 5</div>
|
||||
<p>
|
||||
<input type='checkbox' id='drop-remove' />
|
||||
<label for='drop-remove'>remove after drop</label>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
<div style='clear:both'></div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,78 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script src='../gcal.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,listYear'
|
||||
},
|
||||
|
||||
displayEventTime: false, // don't show the time column in list view
|
||||
|
||||
// THIS KEY WON'T WORK IN PRODUCTION!!!
|
||||
// To make your own Google API key, follow the directions here:
|
||||
// http://fullcalendar.io/docs/google_calendar/
|
||||
googleCalendarApiKey: 'AIzaSyDcnW6WejpTOCffshGDDb4neIrXVUA1EAE',
|
||||
|
||||
// US Holidays
|
||||
events: 'en.usa#holiday@group.v.calendar.google.com',
|
||||
|
||||
eventClick: function(event) {
|
||||
// opens events in a popup window
|
||||
window.open(event.url, 'gcalevent', 'width=700,height=600');
|
||||
return false;
|
||||
},
|
||||
|
||||
loading: function(bool) {
|
||||
$('#loading').toggle(bool);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 40px 10px;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#loading {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='loading'>loading...</div>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,85 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay,listWeek'
|
||||
},
|
||||
defaultDate: '2017-05-12',
|
||||
editable: true,
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
eventLimit: true, // allow "more" link when too many events
|
||||
events: {
|
||||
url: 'php/get-events.php',
|
||||
error: function() {
|
||||
$('#script-warning').show();
|
||||
}
|
||||
},
|
||||
loading: function(bool) {
|
||||
$('#loading').toggle(bool);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#script-warning {
|
||||
display: none;
|
||||
background: #eee;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 0 10px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
#loading {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 40px auto;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='script-warning'>
|
||||
<code>php/get-events.php</code> must be running.
|
||||
</div>
|
||||
|
||||
<div id='loading'>loading...</div>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,56 @@
|
||||
[
|
||||
{
|
||||
"title": "All Day Event",
|
||||
"start": "2017-05-01"
|
||||
},
|
||||
{
|
||||
"title": "Long Event",
|
||||
"start": "2017-05-07",
|
||||
"end": "2017-05-10"
|
||||
},
|
||||
{
|
||||
"id": "999",
|
||||
"title": "Repeating Event",
|
||||
"start": "2017-05-09T16:00:00-05:00"
|
||||
},
|
||||
{
|
||||
"id": "999",
|
||||
"title": "Repeating Event",
|
||||
"start": "2017-05-16T16:00:00-05:00"
|
||||
},
|
||||
{
|
||||
"title": "Conference",
|
||||
"start": "2017-05-11",
|
||||
"end": "2017-05-13"
|
||||
},
|
||||
{
|
||||
"title": "Meeting",
|
||||
"start": "2017-05-12T10:30:00-05:00",
|
||||
"end": "2017-05-12T12:30:00-05:00"
|
||||
},
|
||||
{
|
||||
"title": "Lunch",
|
||||
"start": "2017-05-12T12:00:00-05:00"
|
||||
},
|
||||
{
|
||||
"title": "Meeting",
|
||||
"start": "2017-05-12T14:30:00-05:00"
|
||||
},
|
||||
{
|
||||
"title": "Happy Hour",
|
||||
"start": "2017-05-12T17:30:00-05:00"
|
||||
},
|
||||
{
|
||||
"title": "Dinner",
|
||||
"start": "2017-05-12T20:00:00"
|
||||
},
|
||||
{
|
||||
"title": "Birthday Party",
|
||||
"start": "2017-05-13T07:00:00-05:00"
|
||||
},
|
||||
{
|
||||
"title": "Click for Google",
|
||||
"url": "http://google.com/",
|
||||
"start": "2017-05-28"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,115 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'listDay,listWeek,month'
|
||||
},
|
||||
|
||||
// customize the button names,
|
||||
// otherwise they'd all just say "list"
|
||||
views: {
|
||||
listDay: { buttonText: 'list day' },
|
||||
listWeek: { buttonText: 'list week' }
|
||||
},
|
||||
|
||||
defaultView: 'listWeek',
|
||||
defaultDate: '2017-05-12',
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
editable: true,
|
||||
eventLimit: true, // allow "more" link when too many events
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
start: '2017-05-01'
|
||||
},
|
||||
{
|
||||
title: 'Long Event',
|
||||
start: '2017-05-07',
|
||||
end: '2017-05-10'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-09T16:00:00'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-16T16:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Conference',
|
||||
start: '2017-05-11',
|
||||
end: '2017-05-13'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T10:30:00',
|
||||
end: '2017-05-12T12:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Lunch',
|
||||
start: '2017-05-12T12:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T14:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Happy Hour',
|
||||
start: '2017-05-12T17:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Dinner',
|
||||
start: '2017-05-12T20:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Birthday Party',
|
||||
start: '2017-05-13T07:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Click for Google',
|
||||
url: 'http://google.com/',
|
||||
start: '2017-05-28'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 40px 10px;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,143 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script src='../locale-all.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
var initialLocaleCode = 'en';
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay,listMonth'
|
||||
},
|
||||
defaultDate: '2017-05-12',
|
||||
locale: initialLocaleCode,
|
||||
buttonIcons: false, // show the prev/next text
|
||||
weekNumbers: true,
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
editable: true,
|
||||
eventLimit: true, // allow "more" link when too many events
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
start: '2017-05-01'
|
||||
},
|
||||
{
|
||||
title: 'Long Event',
|
||||
start: '2017-05-07',
|
||||
end: '2017-05-10'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-09T16:00:00'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-16T16:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Conference',
|
||||
start: '2017-05-11',
|
||||
end: '2017-05-13'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T10:30:00',
|
||||
end: '2017-05-12T12:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Lunch',
|
||||
start: '2017-05-12T12:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T14:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Happy Hour',
|
||||
start: '2017-05-12T17:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Dinner',
|
||||
start: '2017-05-12T20:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Birthday Party',
|
||||
start: '2017-05-13T07:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Click for Google',
|
||||
url: 'http://google.com/',
|
||||
start: '2017-05-28'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// build the locale selector's options
|
||||
$.each($.fullCalendar.locales, function(localeCode) {
|
||||
$('#locale-selector').append(
|
||||
$('<option/>')
|
||||
.attr('value', localeCode)
|
||||
.prop('selected', localeCode == initialLocaleCode)
|
||||
.text(localeCode)
|
||||
);
|
||||
});
|
||||
|
||||
// when the selected option changes, dynamically change the calendar option
|
||||
$('#locale-selector').on('change', function() {
|
||||
if (this.value) {
|
||||
$('#calendar').fullCalendar('option', 'locale', this.value);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#top {
|
||||
background: #eee;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 0 10px;
|
||||
line-height: 40px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 40px auto;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='top'>
|
||||
|
||||
Locales:
|
||||
<select id='locale-selector'></select>
|
||||
|
||||
</div>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// This script reads event data from a JSON file and outputs those events which are within the range
|
||||
// supplied by the "start" and "end" GET parameters.
|
||||
//
|
||||
// An optional "timezone" GET parameter will force all ISO8601 date stings to a given timezone.
|
||||
//
|
||||
// Requires PHP 5.2.0 or higher.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
// Require our Event class and datetime utilities
|
||||
require dirname(__FILE__) . '/utils.php';
|
||||
|
||||
// Short-circuit if the client did not give us a date range.
|
||||
if (!isset($_GET['start']) || !isset($_GET['end'])) {
|
||||
die("Please provide a date range.");
|
||||
}
|
||||
|
||||
// Parse the start/end parameters.
|
||||
// These are assumed to be ISO8601 strings with no time nor timezone, like "2013-12-29".
|
||||
// Since no timezone will be present, they will parsed as UTC.
|
||||
$range_start = parseDateTime($_GET['start']);
|
||||
$range_end = parseDateTime($_GET['end']);
|
||||
|
||||
// Parse the timezone parameter if it is present.
|
||||
$timezone = null;
|
||||
if (isset($_GET['timezone'])) {
|
||||
$timezone = new DateTimeZone($_GET['timezone']);
|
||||
}
|
||||
|
||||
// Read and parse our events JSON file into an array of event data arrays.
|
||||
$json = file_get_contents(dirname(__FILE__) . '/../json/events.json');
|
||||
$input_arrays = json_decode($json, true);
|
||||
|
||||
// Accumulate an output array of event data arrays.
|
||||
$output_arrays = array();
|
||||
foreach ($input_arrays as $array) {
|
||||
|
||||
// Convert the input array into a useful Event object
|
||||
$event = new Event($array, $timezone);
|
||||
|
||||
// If the event is in-bounds, add it to the output
|
||||
if ($event->isWithinDayRange($range_start, $range_end)) {
|
||||
$output_arrays[] = $event->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
// Send JSON to the client.
|
||||
echo json_encode($output_arrays);
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// This script outputs a JSON array of all timezones (like "America/Chicago") that PHP supports.
|
||||
//
|
||||
// Requires PHP 5.2.0 or higher.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
echo json_encode(DateTimeZone::listIdentifiers());
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Utilities for our event-fetching scripts.
|
||||
//
|
||||
// Requires PHP 5.2.0 or higher.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
// PHP will fatal error if we attempt to use the DateTime class without this being set.
|
||||
date_default_timezone_set('UTC');
|
||||
|
||||
|
||||
class Event {
|
||||
|
||||
// Tests whether the given ISO8601 string has a time-of-day or not
|
||||
const ALL_DAY_REGEX = '/^\d{4}-\d\d-\d\d$/'; // matches strings like "2013-12-29"
|
||||
|
||||
public $title;
|
||||
public $allDay; // a boolean
|
||||
public $start; // a DateTime
|
||||
public $end; // a DateTime, or null
|
||||
public $properties = array(); // an array of other misc properties
|
||||
|
||||
|
||||
// Constructs an Event object from the given array of key=>values.
|
||||
// You can optionally force the timezone of the parsed dates.
|
||||
public function __construct($array, $timezone=null) {
|
||||
|
||||
$this->title = $array['title'];
|
||||
|
||||
if (isset($array['allDay'])) {
|
||||
// allDay has been explicitly specified
|
||||
$this->allDay = (bool)$array['allDay'];
|
||||
}
|
||||
else {
|
||||
// Guess allDay based off of ISO8601 date strings
|
||||
$this->allDay = preg_match(self::ALL_DAY_REGEX, $array['start']) &&
|
||||
(!isset($array['end']) || preg_match(self::ALL_DAY_REGEX, $array['end']));
|
||||
}
|
||||
|
||||
if ($this->allDay) {
|
||||
// If dates are allDay, we want to parse them in UTC to avoid DST issues.
|
||||
$timezone = null;
|
||||
}
|
||||
|
||||
// Parse dates
|
||||
$this->start = parseDateTime($array['start'], $timezone);
|
||||
$this->end = isset($array['end']) ? parseDateTime($array['end'], $timezone) : null;
|
||||
|
||||
// Record misc properties
|
||||
foreach ($array as $name => $value) {
|
||||
if (!in_array($name, array('title', 'allDay', 'start', 'end'))) {
|
||||
$this->properties[$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns whether the date range of our event intersects with the given all-day range.
|
||||
// $rangeStart and $rangeEnd are assumed to be dates in UTC with 00:00:00 time.
|
||||
public function isWithinDayRange($rangeStart, $rangeEnd) {
|
||||
|
||||
// Normalize our event's dates for comparison with the all-day range.
|
||||
$eventStart = stripTime($this->start);
|
||||
|
||||
if (isset($this->end)) {
|
||||
$eventEnd = stripTime($this->end); // normalize
|
||||
}
|
||||
else {
|
||||
$eventEnd = $eventStart; // consider this a zero-duration event
|
||||
}
|
||||
|
||||
// Check if the two whole-day ranges intersect.
|
||||
return $eventStart < $rangeEnd && $eventEnd >= $rangeStart;
|
||||
}
|
||||
|
||||
|
||||
// Converts this Event object back to a plain data array, to be used for generating JSON
|
||||
public function toArray() {
|
||||
|
||||
// Start with the misc properties (don't worry, PHP won't affect the original array)
|
||||
$array = $this->properties;
|
||||
|
||||
$array['title'] = $this->title;
|
||||
|
||||
// Figure out the date format. This essentially encodes allDay into the date string.
|
||||
if ($this->allDay) {
|
||||
$format = 'Y-m-d'; // output like "2013-12-29"
|
||||
}
|
||||
else {
|
||||
$format = 'c'; // full ISO8601 output, like "2013-12-29T09:00:00+08:00"
|
||||
}
|
||||
|
||||
// Serialize dates into strings
|
||||
$array['start'] = $this->start->format($format);
|
||||
if (isset($this->end)) {
|
||||
$array['end'] = $this->end->format($format);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Date Utilities
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Parses a string into a DateTime object, optionally forced into the given timezone.
|
||||
function parseDateTime($string, $timezone=null) {
|
||||
$date = new DateTime(
|
||||
$string,
|
||||
$timezone ? $timezone : new DateTimeZone('UTC')
|
||||
// Used only when the string is ambiguous.
|
||||
// Ignored if string has a timezone offset in it.
|
||||
);
|
||||
if ($timezone) {
|
||||
// If our timezone was ignored above, force it.
|
||||
$date->setTimezone($timezone);
|
||||
}
|
||||
return $date;
|
||||
}
|
||||
|
||||
|
||||
// Takes the year/month/date values of the given DateTime and converts them to a new DateTime,
|
||||
// but in UTC.
|
||||
function stripTime($datetime) {
|
||||
return new DateTime($datetime->format('Y-m-d'));
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay'
|
||||
},
|
||||
defaultDate: '2017-05-12',
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
selectable: true,
|
||||
selectHelper: true,
|
||||
select: function(start, end) {
|
||||
var title = prompt('Event Title:');
|
||||
var eventData;
|
||||
if (title) {
|
||||
eventData = {
|
||||
title: title,
|
||||
start: start,
|
||||
end: end
|
||||
};
|
||||
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
|
||||
}
|
||||
$('#calendar').fullCalendar('unselect');
|
||||
},
|
||||
editable: true,
|
||||
eventLimit: true, // allow "more" link when too many events
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
start: '2017-05-01'
|
||||
},
|
||||
{
|
||||
title: 'Long Event',
|
||||
start: '2017-05-07',
|
||||
end: '2017-05-10'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-09T16:00:00'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-16T16:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Conference',
|
||||
start: '2017-05-11',
|
||||
end: '2017-05-13'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T10:30:00',
|
||||
end: '2017-05-12T12:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Lunch',
|
||||
start: '2017-05-12T12:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T14:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Happy Hour',
|
||||
start: '2017-05-12T17:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Dinner',
|
||||
start: '2017-05-12T20:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Birthday Party',
|
||||
start: '2017-05-13T07:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Click for Google',
|
||||
url: 'http://google.com/',
|
||||
start: '2017-05-28'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 40px 10px;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,108 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link rel='stylesheet' href='../lib/cupertino/jquery-ui.min.css' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
theme: true,
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay,listMonth'
|
||||
},
|
||||
defaultDate: '2017-05-12',
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
editable: true,
|
||||
eventLimit: true, // allow "more" link when too many events
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
start: '2017-05-01'
|
||||
},
|
||||
{
|
||||
title: 'Long Event',
|
||||
start: '2017-05-07',
|
||||
end: '2017-05-10'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-09T16:00:00'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-16T16:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Conference',
|
||||
start: '2017-05-11',
|
||||
end: '2017-05-13'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T10:30:00',
|
||||
end: '2017-05-12T12:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Lunch',
|
||||
start: '2017-05-12T12:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T14:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Happy Hour',
|
||||
start: '2017-05-12T17:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Dinner',
|
||||
start: '2017-05-12T20:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Birthday Party',
|
||||
start: '2017-05-13T07:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Click for Google',
|
||||
url: 'http://google.com/',
|
||||
start: '2017-05-28'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 40px 10px;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,128 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay,listWeek'
|
||||
},
|
||||
defaultDate: '2017-05-12',
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
editable: true,
|
||||
selectable: true,
|
||||
eventLimit: true, // allow "more" link when too many events
|
||||
events: {
|
||||
url: 'php/get-events.php',
|
||||
error: function() {
|
||||
$('#script-warning').show();
|
||||
}
|
||||
},
|
||||
loading: function(bool) {
|
||||
$('#loading').toggle(bool);
|
||||
},
|
||||
eventRender: function(event, el) {
|
||||
// render the timezone offset below the event title
|
||||
if (event.start.hasZone()) {
|
||||
el.find('.fc-title').after(
|
||||
$('<div class="tzo"/>').text(event.start.format('Z'))
|
||||
);
|
||||
}
|
||||
},
|
||||
dayClick: function(date) {
|
||||
console.log('dayClick', date.format());
|
||||
},
|
||||
select: function(startDate, endDate) {
|
||||
console.log('select', startDate.format(), endDate.format());
|
||||
}
|
||||
});
|
||||
|
||||
// load the list of available timezones, build the <select> options
|
||||
$.getJSON('php/get-timezones.php', function(timezones) {
|
||||
$.each(timezones, function(i, timezone) {
|
||||
if (timezone != 'UTC') { // UTC is already in the list
|
||||
$('#timezone-selector').append(
|
||||
$("<option/>").text(timezone).attr('value', timezone)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// when the timezone selector changes, dynamically change the calendar option
|
||||
$('#timezone-selector').on('change', function() {
|
||||
$('#calendar').fullCalendar('option', 'timezone', this.value || false);
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#top {
|
||||
background: #eee;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 0 10px;
|
||||
line-height: 40px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.left { float: left }
|
||||
.right { float: right }
|
||||
.clear { clear: both }
|
||||
|
||||
#script-warning, #loading { display: none }
|
||||
#script-warning { font-weight: bold; color: red }
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 40px auto;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.tzo {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='top'>
|
||||
|
||||
<div class='left'>
|
||||
Timezone:
|
||||
<select id='timezone-selector'>
|
||||
<option value='' selected>none</option>
|
||||
<option value='local'>local</option>
|
||||
<option value='UTC'>UTC</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class='right'>
|
||||
<span id='loading'>loading...</span>
|
||||
<span id='script-warning'><code>php/get-events.php</code> must be running.</span>
|
||||
</div>
|
||||
|
||||
<div class='clear'></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,111 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<link href='../fullcalendar.min.css' rel='stylesheet' />
|
||||
<link href='../fullcalendar.print.min.css' rel='stylesheet' media='print' />
|
||||
<script src='../lib/moment.min.js'></script>
|
||||
<script src='../lib/jquery.min.js'></script>
|
||||
<script src='../fullcalendar.min.js'></script>
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#calendar').fullCalendar({
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month,agendaWeek,agendaDay,listWeek'
|
||||
},
|
||||
defaultDate: '2017-05-12',
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
|
||||
weekNumbers: true,
|
||||
weekNumbersWithinDays: true,
|
||||
weekNumberCalculation: 'ISO',
|
||||
|
||||
editable: true,
|
||||
eventLimit: true, // allow "more" link when too many events
|
||||
events: [
|
||||
{
|
||||
title: 'All Day Event',
|
||||
start: '2017-05-01'
|
||||
},
|
||||
{
|
||||
title: 'Long Event',
|
||||
start: '2017-05-07',
|
||||
end: '2017-05-10'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-09T16:00:00'
|
||||
},
|
||||
{
|
||||
id: 999,
|
||||
title: 'Repeating Event',
|
||||
start: '2017-05-16T16:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Conference',
|
||||
start: '2017-05-11',
|
||||
end: '2017-05-13'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T10:30:00',
|
||||
end: '2017-05-12T12:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Lunch',
|
||||
start: '2017-05-12T12:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Meeting',
|
||||
start: '2017-05-12T14:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Happy Hour',
|
||||
start: '2017-05-12T17:30:00'
|
||||
},
|
||||
{
|
||||
title: 'Dinner',
|
||||
start: '2017-05-12T20:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Birthday Party',
|
||||
start: '2017-05-13T07:00:00'
|
||||
},
|
||||
{
|
||||
title: 'Click for Google',
|
||||
url: 'http://google.com/',
|
||||
start: '2017-05-28'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 40px 10px;
|
||||
padding: 0;
|
||||
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#calendar {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='calendar'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,208 @@
|
||||
/*!
|
||||
* FullCalendar v3.4.0 Print Stylesheet
|
||||
* Docs & License: https://fullcalendar.io/
|
||||
* (c) 2017 Adam Shaw
|
||||
*/
|
||||
|
||||
/*
|
||||
* Include this stylesheet on your page to get a more printer-friendly calendar.
|
||||
* When including this stylesheet, use the media='print' attribute of the <link> tag.
|
||||
* Make sure to include this stylesheet IN ADDITION to the regular fullcalendar.css.
|
||||
*/
|
||||
|
||||
.fc {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
|
||||
/* Global Event Restyling
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
.fc-event {
|
||||
background: #fff !important;
|
||||
color: #000 !important;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.fc-event .fc-resizer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* Table & Day-Row Restyling
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
.fc th,
|
||||
.fc td,
|
||||
.fc hr,
|
||||
.fc thead,
|
||||
.fc tbody,
|
||||
.fc-row {
|
||||
border-color: #ccc !important;
|
||||
background: #fff !important;
|
||||
}
|
||||
|
||||
/* kill the overlaid, absolutely-positioned components */
|
||||
/* common... */
|
||||
.fc-bg,
|
||||
.fc-bgevent-skeleton,
|
||||
.fc-highlight-skeleton,
|
||||
.fc-helper-skeleton,
|
||||
/* for timegrid. within cells within table skeletons... */
|
||||
.fc-bgevent-container,
|
||||
.fc-business-container,
|
||||
.fc-highlight-container,
|
||||
.fc-helper-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* don't force a min-height on rows (for DayGrid) */
|
||||
.fc tbody .fc-row {
|
||||
height: auto !important; /* undo height that JS set in distributeHeight */
|
||||
min-height: 0 !important; /* undo the min-height from each view's specific stylesheet */
|
||||
}
|
||||
|
||||
.fc tbody .fc-row .fc-content-skeleton {
|
||||
position: static; /* undo .fc-rigid */
|
||||
padding-bottom: 0 !important; /* use a more border-friendly method for this... */
|
||||
}
|
||||
|
||||
.fc tbody .fc-row .fc-content-skeleton tbody tr:last-child td { /* only works in newer browsers */
|
||||
padding-bottom: 1em; /* ...gives space within the skeleton. also ensures min height in a way */
|
||||
}
|
||||
|
||||
.fc tbody .fc-row .fc-content-skeleton table {
|
||||
/* provides a min-height for the row, but only effective for IE, which exaggerates this value,
|
||||
making it look more like 3em. for other browers, it will already be this tall */
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
|
||||
/* Undo month-view event limiting. Display all events and hide the "more" links
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
.fc-more-cell,
|
||||
.fc-more {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.fc tr.fc-limited {
|
||||
display: table-row !important;
|
||||
}
|
||||
|
||||
.fc td.fc-limited {
|
||||
display: table-cell !important;
|
||||
}
|
||||
|
||||
.fc-popover {
|
||||
display: none; /* never display the "more.." popover in print mode */
|
||||
}
|
||||
|
||||
|
||||
/* TimeGrid Restyling
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* undo the min-height 100% trick used to fill the container's height */
|
||||
.fc-time-grid {
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
/* don't display the side axis at all ("all-day" and time cells) */
|
||||
.fc-agenda-view .fc-axis {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* don't display the horizontal lines */
|
||||
.fc-slats,
|
||||
.fc-time-grid hr { /* this hr is used when height is underused and needs to be filled */
|
||||
display: none !important; /* important overrides inline declaration */
|
||||
}
|
||||
|
||||
/* let the container that holds the events be naturally positioned and create real height */
|
||||
.fc-time-grid .fc-content-skeleton {
|
||||
position: static;
|
||||
}
|
||||
|
||||
/* in case there are no events, we still want some height */
|
||||
.fc-time-grid .fc-content-skeleton table {
|
||||
height: 4em;
|
||||
}
|
||||
|
||||
/* kill the horizontal spacing made by the event container. event margins will be done below */
|
||||
.fc-time-grid .fc-event-container {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
/* TimeGrid *Event* Restyling
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* naturally position events, vertically stacking them */
|
||||
.fc-time-grid .fc-event {
|
||||
position: static !important;
|
||||
margin: 3px 2px !important;
|
||||
}
|
||||
|
||||
/* for events that continue to a future day, give the bottom border back */
|
||||
.fc-time-grid .fc-event.fc-not-end {
|
||||
border-bottom-width: 1px !important;
|
||||
}
|
||||
|
||||
/* indicate the event continues via "..." text */
|
||||
.fc-time-grid .fc-event.fc-not-end:after {
|
||||
content: "...";
|
||||
}
|
||||
|
||||
/* for events that are continuations from previous days, give the top border back */
|
||||
.fc-time-grid .fc-event.fc-not-start {
|
||||
border-top-width: 1px !important;
|
||||
}
|
||||
|
||||
/* indicate the event is a continuation via "..." text */
|
||||
.fc-time-grid .fc-event.fc-not-start:before {
|
||||
content: "...";
|
||||
}
|
||||
|
||||
/* time */
|
||||
|
||||
/* undo a previous declaration and let the time text span to a second line */
|
||||
.fc-time-grid .fc-event .fc-time {
|
||||
white-space: normal !important;
|
||||
}
|
||||
|
||||
/* hide the the time that is normally displayed... */
|
||||
.fc-time-grid .fc-event .fc-time span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ...replace it with a more verbose version (includes AM/PM) stored in an html attribute */
|
||||
.fc-time-grid .fc-event .fc-time:after {
|
||||
content: attr(data-full);
|
||||
}
|
||||
|
||||
|
||||
/* Vertical Scroller & Containers
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* kill the scrollbars and allow natural height */
|
||||
.fc-scroller,
|
||||
.fc-day-grid-container, /* these divs might be assigned height, which we need to cleared */
|
||||
.fc-time-grid-container { /* */
|
||||
overflow: visible !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
/* kill the horizontal border/padding used to compensate for scrollbars */
|
||||
.fc-row {
|
||||
border: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
/* Button Controls
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
.fc-button-group,
|
||||
.fc button {
|
||||
display: none; /* don't display any button-related controls */
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* FullCalendar v3.4.0 Print Stylesheet
|
||||
* Docs & License: https://fullcalendar.io/
|
||||
* (c) 2017 Adam Shaw
|
||||
*/.fc-bg,.fc-bgevent-container,.fc-bgevent-skeleton,.fc-business-container,.fc-event .fc-resizer,.fc-helper-container,.fc-helper-skeleton,.fc-highlight-container,.fc-highlight-skeleton{display:none}.fc tbody .fc-row,.fc-time-grid{min-height:0!important}.fc-time-grid .fc-event.fc-not-end:after,.fc-time-grid .fc-event.fc-not-start:before{content:"..."}.fc{max-width:100%!important}.fc-event{background:#fff!important;color:#000!important;page-break-inside:avoid}.fc hr,.fc tbody,.fc td,.fc th,.fc thead,.fc-row{border-color:#ccc!important;background:#fff!important}.fc tbody .fc-row{height:auto!important}.fc tbody .fc-row .fc-content-skeleton{position:static;padding-bottom:0!important}.fc tbody .fc-row .fc-content-skeleton tbody tr:last-child td{padding-bottom:1em}.fc tbody .fc-row .fc-content-skeleton table{height:1em}.fc-more,.fc-more-cell{display:none!important}.fc tr.fc-limited{display:table-row!important}.fc td.fc-limited{display:table-cell!important}.fc-agenda-view .fc-axis,.fc-popover{display:none}.fc-slats,.fc-time-grid hr{display:none!important}.fc button,.fc-button-group,.fc-time-grid .fc-event .fc-time span{display:none}.fc-time-grid .fc-content-skeleton{position:static}.fc-time-grid .fc-content-skeleton table{height:4em}.fc-time-grid .fc-event-container{margin:0!important}.fc-time-grid .fc-event{position:static!important;margin:3px 2px!important}.fc-time-grid .fc-event.fc-not-end{border-bottom-width:1px!important}.fc-time-grid .fc-event.fc-not-start{border-top-width:1px!important}.fc-time-grid .fc-event .fc-time{white-space:normal!important}.fc-time-grid .fc-event .fc-time:after{content:attr(data-full)}.fc-day-grid-container,.fc-scroller,.fc-time-grid-container{overflow:visible!important;height:auto!important}.fc-row{border:0!important;margin:0!important}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*!
|
||||
* FullCalendar v3.4.0 Google Calendar Plugin
|
||||
* Docs & License: https://fullcalendar.io/
|
||||
* (c) 2017 Adam Shaw
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([ 'jquery' ], factory);
|
||||
}
|
||||
else if (typeof exports === 'object') { // Node/CommonJS
|
||||
module.exports = factory(require('jquery'));
|
||||
}
|
||||
else {
|
||||
factory(jQuery);
|
||||
}
|
||||
})(function($) {
|
||||
|
||||
|
||||
var API_BASE = 'https://www.googleapis.com/calendar/v3/calendars';
|
||||
var FC = $.fullCalendar;
|
||||
var applyAll = FC.applyAll;
|
||||
|
||||
|
||||
FC.sourceNormalizers.push(function(sourceOptions) {
|
||||
var googleCalendarId = sourceOptions.googleCalendarId;
|
||||
var url = sourceOptions.url;
|
||||
var match;
|
||||
|
||||
// if the Google Calendar ID hasn't been explicitly defined
|
||||
if (!googleCalendarId && url) {
|
||||
|
||||
// detect if the ID was specified as a single string.
|
||||
// will match calendars like "asdf1234@calendar.google.com" in addition to person email calendars.
|
||||
if (/^[^\/]+@([^\/\.]+\.)*(google|googlemail|gmail)\.com$/.test(url)) {
|
||||
googleCalendarId = url;
|
||||
}
|
||||
// try to scrape it out of a V1 or V3 API feed URL
|
||||
else if (
|
||||
(match = /^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^\/]*)/.exec(url)) ||
|
||||
(match = /^https?:\/\/www.google.com\/calendar\/feeds\/([^\/]*)/.exec(url))
|
||||
) {
|
||||
googleCalendarId = decodeURIComponent(match[1]);
|
||||
}
|
||||
|
||||
if (googleCalendarId) {
|
||||
sourceOptions.googleCalendarId = googleCalendarId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (googleCalendarId) { // is this a Google Calendar?
|
||||
|
||||
// make each Google Calendar source uneditable by default
|
||||
if (sourceOptions.editable == null) {
|
||||
sourceOptions.editable = false;
|
||||
}
|
||||
|
||||
// We want removeEventSource to work, but it won't know about the googleCalendarId primitive.
|
||||
// Shoehorn it into the url, which will function as the unique primitive. Won't cause side effects.
|
||||
// This hack is obsolete since 2.2.3, but keep it so this plugin file is compatible with old versions.
|
||||
sourceOptions.url = googleCalendarId;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
FC.sourceFetchers.push(function(sourceOptions, start, end, timezone) {
|
||||
if (sourceOptions.googleCalendarId) {
|
||||
return transformOptions(sourceOptions, start, end, timezone, this); // `this` is the calendar
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function transformOptions(sourceOptions, start, end, timezone, calendar) {
|
||||
var url = API_BASE + '/' + encodeURIComponent(sourceOptions.googleCalendarId) + '/events?callback=?'; // jsonp
|
||||
var apiKey = sourceOptions.googleCalendarApiKey || calendar.opt('googleCalendarApiKey');
|
||||
var success = sourceOptions.success;
|
||||
var data;
|
||||
var timezoneArg; // populated when a specific timezone. escaped to Google's liking
|
||||
|
||||
function reportError(message, apiErrorObjs) {
|
||||
var errorObjs = apiErrorObjs || [ { message: message } ]; // to be passed into error handlers
|
||||
|
||||
// call error handlers
|
||||
(sourceOptions.googleCalendarError || $.noop).apply(calendar, errorObjs);
|
||||
(calendar.opt('googleCalendarError') || $.noop).apply(calendar, errorObjs);
|
||||
|
||||
// print error to debug console
|
||||
FC.warn.apply(null, [ message ].concat(apiErrorObjs || []));
|
||||
}
|
||||
|
||||
if (!apiKey) {
|
||||
reportError("Specify a googleCalendarApiKey. See http://fullcalendar.io/docs/google_calendar/");
|
||||
return {}; // an empty source to use instead. won't fetch anything.
|
||||
}
|
||||
|
||||
// The API expects an ISO8601 datetime with a time and timezone part.
|
||||
// Since the calendar's timezone offset isn't always known, request the date in UTC and pad it by a day on each
|
||||
// side, guaranteeing we will receive all events in the desired range, albeit a superset.
|
||||
// .utc() will set a zone and give it a 00:00:00 time.
|
||||
if (!start.hasZone()) {
|
||||
start = start.clone().utc().add(-1, 'day');
|
||||
}
|
||||
if (!end.hasZone()) {
|
||||
end = end.clone().utc().add(1, 'day');
|
||||
}
|
||||
|
||||
// when sending timezone names to Google, only accepts underscores, not spaces
|
||||
if (timezone && timezone != 'local') {
|
||||
timezoneArg = timezone.replace(' ', '_');
|
||||
}
|
||||
|
||||
data = $.extend({}, sourceOptions.data || {}, {
|
||||
key: apiKey,
|
||||
timeMin: start.format(),
|
||||
timeMax: end.format(),
|
||||
timeZone: timezoneArg,
|
||||
singleEvents: true,
|
||||
maxResults: 9999
|
||||
});
|
||||
|
||||
return $.extend({}, sourceOptions, {
|
||||
googleCalendarId: null, // prevents source-normalizing from happening again
|
||||
url: url,
|
||||
data: data,
|
||||
startParam: false, // `false` omits this parameter. we already included it above
|
||||
endParam: false, // same
|
||||
timezoneParam: false, // same
|
||||
success: function(data) {
|
||||
var events = [];
|
||||
var successArgs;
|
||||
var successRes;
|
||||
|
||||
if (data.error) {
|
||||
reportError('Google Calendar API: ' + data.error.message, data.error.errors);
|
||||
}
|
||||
else if (data.items) {
|
||||
$.each(data.items, function(i, entry) {
|
||||
var url = entry.htmlLink || null;
|
||||
|
||||
// make the URLs for each event show times in the correct timezone
|
||||
if (timezoneArg && url !== null) {
|
||||
url = injectQsComponent(url, 'ctz=' + timezoneArg);
|
||||
}
|
||||
|
||||
events.push({
|
||||
id: entry.id,
|
||||
title: entry.summary,
|
||||
start: entry.start.dateTime || entry.start.date, // try timed. will fall back to all-day
|
||||
end: entry.end.dateTime || entry.end.date, // same
|
||||
url: url,
|
||||
location: entry.location,
|
||||
description: entry.description
|
||||
});
|
||||
});
|
||||
|
||||
// call the success handler(s) and allow it to return a new events array
|
||||
successArgs = [ events ].concat(Array.prototype.slice.call(arguments, 1)); // forward other jq args
|
||||
successRes = applyAll(success, this, successArgs);
|
||||
if ($.isArray(successRes)) {
|
||||
return successRes;
|
||||
}
|
||||
}
|
||||
|
||||
return events;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Injects a string like "arg=value" into the querystring of a URL
|
||||
function injectQsComponent(url, component) {
|
||||
// inject it after the querystring but before the fragment
|
||||
return url.replace(/(\?.*?)?(#|$)/, function(whole, qs, hash) {
|
||||
return (qs ? qs + '&' : '?') + component + hash;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user