(function (angular) {
var undefined;
angular.module("ui.materialize", ["ui.materialize.ngModel", "ui.materialize.collapsible", "ui.materialize.toast", "ui.materialize.sidenav", "ui.materialize.material_select", "ui.materialize.dropdown", "ui.materialize.inputfield", "ui.materialize.input_date", "ui.materialize.tabs", "ui.materialize.pagination", "ui.materialize.pushpin", "ui.materialize.scrollspy", "ui.materialize.parallax","ui.materialize.modal", "ui.materialize.tooltipped", "ui.materialize.slider", "ui.materialize.materialboxed", "ui.materialize.scrollFire", "ui.materialize.nouislider", "ui.materialize.input_clock", "ui.materialize.carousel"]);
/* example usage:
*/
angular.module("ui.materialize.scrollFire", [])
.directive("scrollFire", ["$compile", "$timeout", function ($compile, $timeout) {
return {
restrict: "A",
scope: {
offset: "@",
scrollFire: "&"
},
link: function (scope, element, attrs) {
var offset = scope.offset;
if (!angular.isDefined(scope.offset)) {
offset = 0;
}
offset = Number(offset) || 0;
var fired = false;
var handler = throttle(function () {
if (fired) {
return;
}
var windowScroll = window.pageYOffset + window.innerHeight;
var elementOffset = element[0].getBoundingClientRect().top + window.pageYOffset;
if (windowScroll > (elementOffset + offset)) {
fired = true;
scope.scrollFire({});
stop();
}
}, 100);
function stop() {
$(window).off("scroll resize blur focus", handler);
}
$(window).on("scroll resize blur focus", handler);
handler();
scope.$on('$destroy', stop);
}
};
}]);
// The throttle function from underscore: https://github.com/jashkenas/underscore/blob/master/underscore.js
function throttle(func, wait) {
var timeout, context, args, result;
var previous = 0;
var later = function() {
previous = + new Date();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
var throttled = function() {
var now = + new Date();
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout) {
timeout = setTimeout(later, remaining);
}
return result;
};
throttled.cancel = function() {
clearTimeout(timeout);
previous = 0;
timeout = context = args = null;
};
return throttled;
};
angular.module("ui.materialize.ngModel", [])
.directive("ngModel",["$timeout", function($timeout){
return {
restrict: 'A',
priority: -1, // lower priority than built-in ng-model so it runs first
link: function(scope, element, attr) {
scope.$watch(attr.ngModel,function(value, oldValue){
$timeout(function () {
// To stop an infinite feedback-loop with material multiple-select.
if (value instanceof Array && oldValue instanceof Array) {
if (value.length == oldValue.length) {
return;
}
}
if (element.is('select')) {
return;
}
// This fix is mainly to get placeholders to appear correctly, and it apparently screws things for the selects, so only doing this on something that isn't a select.
if (value){
element.trigger("change");
} else if(element.attr('placeholder') === undefined) {
if(!element.is(":focus"))
element.trigger("blur");
}
});
});
}
};
}]);
/* example usage:
*/
angular.module("ui.materialize.slider", [])
.directive("slider", ["$timeout", function($timeout){
return {
restrict: 'A',
scope: {
height: '=',
transition: '=',
interval: '=',
indicators: '='
},
link: function(scope, element, attrs) {
element.addClass("slider");
$timeout(function(){
element.slider({
height: (angular.isDefined(scope.height)) ? scope.height : 400,
transition: (angular.isDefined(scope.transition)) ? scope.transition : 500,
interval: (angular.isDefined(scope.interval)) ? scope.interval : 6000,
indicators: (angular.isDefined(scope.indicators)) ? scope.indicators : true
});
});
}
};
}]);
/* example usage:
*/
angular.module("ui.materialize.carousel", [])
.directive("carousel", ["$timeout", function($timeout){
return {
restrict: 'A',
scope: {
timeConstant: '@',
dist: '@',
shift: '@',
padding: '@',
fullWidth: '@',
indicators: '@',
noWrap: '@'
},
link: function(scope, element, attrs) {
element.addClass("carousel");
$timeout(function(){
element.carousel({
time_constant: (angular.isDefined(scope.timeConstant)) ? scope.timeConstant : 200,
dist: (angular.isDefined(scope.dist)) ? scope.dist : -100,
shift: (angular.isDefined(scope.shift)) ? scope.shift : 0,
padding: (angular.isDefined(scope.padding)) ? scope.padding : 0,
full_width: (angular.isDefined(scope.fullWidth)) ? scope.fullWidth : false,
indicators: (angular.isDefined(scope.indicators)) ? scope.indicators : false,
no_wrap: (angular.isDefined(scope.noWrap)) ? scope.noWrap : false
});
});
}
};
}]);
angular.module("ui.materialize.collapsible", [])
.directive("collapsible", ["$timeout", function ($timeout) {
return {
link: function (scope, element, attrs) {
$timeout(function () {
element.collapsible();
});
if ("watch" in attrs) {
scope.$watch(function () {
return element[0].innerHTML;
}, function (oldVal, newVal) {
if (oldVal !== newVal) {
$timeout(function () {
element.collapsible();
});
}
});
}
}
};
}]);
angular.module("ui.materialize.parallax", [])
.directive("parallax", ["$timeout", function($timeout){
return {
link: function(scope, element, attrs) {
$timeout(function(){
element.parallax();
});
}
};
}]);
angular.module("ui.materialize.toast", [])
.constant("toastConfig", {
duration: 3000
})
.directive("toast", ["toastConfig", function (toastConfig) {
return {
scope: {
message: "@",
duration: "@",
callback: "&"
},
link: function (scope, element, attrs) {
element.bind(attrs.toast, function () {
var message = (angular.isDefined(scope.message)) ? scope.message : "";
var toastclass = (angular.isDefined(attrs.toastclass)) ? attrs.toastclass : "";
Materialize.toast(message, scope.duration ? scope.duration : toastConfig.duration, toastclass, scope.callback);
});
}
};
}]);
angular.module('ui.materialize.pushpin', [])
.directive('pushpin', [function(){
return {
restrict: 'AE',
require: [
'?pushpinTop',
'?pushpinOffset',
'?pushpinBottom'
],
link: function (scope, element, attrs) {
var top = attrs.pushpinTop || 0;
var offset = attrs.pushpinOffset || 0;
var bottom = attrs.pushpinBottom || Infinity;
setTimeout(function () {
element.pushpin({top: top, offset: offset, bottom: bottom});
}, 0);
}
};
}]);
// TODO: Add some documentation for this.
angular.module("ui.materialize.scrollspy", [])
.directive("scrollspy", ["$timeout", function($timeout){
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.addClass("scrollspy");
$timeout(function(){
element.scrollSpy();
});
}
};
}]);
angular.module("ui.materialize.tabs", [])
.directive("tabs", ["$timeout", function($timeout){
return {
scope: {
reload: '='
},
link: function (scope, element, attrs) {
element.addClass("tabs");
$timeout(function() {
element.tabs();
});
scope.$watch('reload', function(newValue) {
if (newValue === true) {
element.tabs();
scope.reload = false;
}
});
}
};
}]);
// Example:
// data-activates is handled by the jQuery plugin.
angular.module("ui.materialize.sidenav", [])
.directive("sidenav", [function () {
return {
scope: {
menuwidth: "@",
closeonclick: "@"
},
link: function (scope, element, attrs) {
element.sideNav({
menuWidth: (angular.isDefined(scope.menuwidth)) ? parseInt(scope.menuwidth, 10) : undefined,
edge: attrs.sidenav ? attrs.sidenav : "left",
closeOnClick: (angular.isDefined(scope.closeonclick)) ? scope.closeonclick == "true" : undefined
});
}
};
}]);
// This works, unless the content inside the select changes.
angular.module("ui.materialize.material_select", [])
.directive("materialSelect", ["$compile", "$timeout", function ($compile, $timeout) {
return {
link: function (scope, element, attrs) {
if (element.is("select")) {
//BugFix 139: In case of multiple enabled. Avoid the circular looping.
function initSelect(newVal, oldVal) {
if (attrs.multiple) {
if (oldVal !== undefined && newVal !== undefined) {
if (oldVal.length === newVal.length) {
return;
}
}
var activeUl = element.siblings("ul.active");
if (newVal !== undefined && activeUl.length) { // If select is open
var selectedOptions = activeUl.children("li.active").length; // Number of selected elements
if (selectedOptions == newVal.length) {
return;
}
}
}
element.siblings(".caret").remove();
function fixActive () {
if (!attrs.multiple) {
var value = element.val();
var ul = element.siblings("ul");
ul.find("li").each(function () {
var that = $(this);
if (that.text() === value) {
that.addClass("active");
}
});
}
}
scope.$evalAsync(function () {
//element.material_select();
//Lines 301-311 fix Dogfalo/materialize/issues/901 and should be removed and the above uncommented whenever 901 is fixed
element.material_select(function () {
if (!attrs.multiple) {
element.siblings('input.select-dropdown').trigger('close');
}
fixActive();
});
var onMouseDown = function (e) {
// preventing the default still allows the scroll, but blocks the blur.
// We're inside the scrollbar if the clientX is >= the clientWidth.
if (e.clientX >= e.target.clientWidth || e.clientY >= e.target.clientHeight) {
e.preventDefault();
}
};
element.siblings('input.select-dropdown').off("mousedown.material_select_fix").on('mousedown.material_select_fix', onMouseDown);
fixActive();
element.siblings('input.select-dropdown').off("click.material_select_fix").on("click.material_select_fix", function () {
$("input.select-dropdown").not(element.siblings("input.select-dropdown")).trigger("close");
});
});
}
$timeout(initSelect);
if (attrs.ngModel) {
if (attrs.ngModel && !angular.isDefined(scope.$eval(attrs.ngModel))) {
// This whole thing fixes that if initialized with undefined, then a ghost value option is inserted. If this thing wasn't done, then adding the 'watch' attribute could also fix it. #160
var hasChangedFromUndefined = false;
scope.$watch(attrs.ngModel, function (newVal, oldVal) {
if (!hasChangedFromUndefined && angular.isDefined(scope.$eval(attrs.ngModel))) {
hasChangedFromUndefined = true;
initSelect(); // initSelect without arguments forces it to actually run.
} else {
initSelect(newVal, oldVal);
}
});
} else {
scope.$watch(attrs.ngModel, initSelect);
}
}
if ("watch" in attrs) {
scope.$watch(function () {
return element[0].innerHTML;
}, function (newValue, oldValue) {
if (newValue !== oldValue) {
$timeout(initSelect);
}
});
}
if(attrs.ngDisabled) {
scope.$watch(attrs.ngDisabled, initSelect)
}
}
}
};
}]);
/*
Example usage, notice the empty dropdown tag in the dropdown trigger.
Select a demo
*/
angular.module("ui.materialize.dropdown", [])
.directive("dropdown", ["$timeout", function ($timeout) {
return {
scope: {
inDuration: "@",
outDuration: "@",
constrainWidth: "@",
hover: "@",
alignment: "@",
gutter: "@",
belowOrigin: "@"
},
link: function (scope, element, attrs) {
$timeout(function () {
element.dropdown({
inDuration: (angular.isDefined(scope.inDuration)) ? scope.inDuration : undefined,
outDuration: (angular.isDefined(scope.outDuration)) ? scope.outDuration : undefined,
constrain_width: (angular.isDefined(scope.constrainWidth)) ? scope.constrainWidth : undefined,
hover: (angular.isDefined(scope.hover)) ? scope.hover : undefined,
alignment: (angular.isDefined(scope.alignment)) ? scope.alignment : undefined,
gutter: (angular.isDefined(scope.gutter)) ? scope.gutter : undefined,
belowOrigin: (angular.isDefined(scope.belowOrigin)) ? scope.belowOrigin : undefined
});
});
}
};
}]);
/**
* Instead of adding the .input-field class to a div surrounding a label and input, add the attribute input-field.
* That way it will also work when angular destroys/recreates the elements.
*
* Example:
*/
angular.module("ui.materialize.inputfield", [])
.directive('inputField', ["$timeout", function ($timeout) {
var inputLabelIdCounter = 0;
return {
transclude: true,
scope: {},
link: function (scope, element) {
$timeout(function () {
var input = element.find("> > input, > > textarea");
var label = element.find("> > label");
if (input.length == 1 && label.length == 1 && !input.attr("id") && !label.attr("for")) {
var id = "angularMaterializeID" + inputLabelIdCounter++;
input.attr("id", id);
label.attr("for", id);
}
Materialize.updateTextFields();
// The "> > [selector]", is to restrict to only those tags that are direct children of the directive element. Otherwise we might hit to many elements with the selectors.
// Triggering autoresize of the textareas.
element.find("> > .materialize-textarea").each(function () {
var that = $(this);
that.addClass("materialize-textarea");
that.trigger("autoresize");
var model = that.attr("ng-model");
if (model) {
scope.$parent.$watch(model, function (a, b) {
if (a !== b) {
$timeout(function () {
that.trigger("autoresize");
});
}
});
}
});
// Adding char-counters.
element.find('> > .materialize-textarea, > > input').each(function (index, countable) {
countable = angular.element(countable);
if (!countable.siblings('span[class="character-counter"]').length) {
countable.characterCounter();
}
});
});
},
template: ''
};
}]);
/**
* Add pickadate directive
* Type text is mandatory
* Example:
*/
angular.module("ui.materialize.input_date", [])
.directive('inputDate', ["$compile", "$timeout", function ($compile, $timeout) {
// Fix for issue 46. This gotta be a bug in the materialize code, but this fixes it.
var style = $('');
$('html > head').append(style);
// Define Prototype Date format
// Use like this
// today = new Date();
// var dateString = today.format("dd-m-yy");
var dateFormat = function () {
var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
timezoneClip = /[^-+\dA-Z]/g,
pad = function (val, len) {
val = String(val);
len = len || 2;
while (val.length < len) {
val = "0" + val;
}
return val;
};
// Regexes and supporting functions are cached through closure
return function (date, mask, utc) {
var dF = dateFormat;
// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
if (arguments.length === 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
mask = date;
date = undefined;
}
// Passing date through Date applies Date.parse, if necessary
date = date ? new Date(date) : new Date();
if (isNaN(date)) throw SyntaxError("invalid date");
mask = String(dF.masks[mask] || mask || dF.masks["default"]);
// Allow setting the utc argument via the mask
if (mask.slice(0, 4) == "UTC:") {
mask = mask.slice(4);
utc = true;
}
var _ = utc ? "getUTC" : "get",
d = date[ _ + "Date" ](),
D = date[ _ + "Day" ](),
m = date[ _ + "Month" ](),
y = date[ _ + "FullYear" ](),
H = date[ _ + "Hours" ](),
M = date[ _ + "Minutes" ](),
s = date[ _ + "Seconds" ](),
L = date[ _ + "Milliseconds" ](),
o = utc ? 0 : date.getTimezoneOffset(),
flags = {
d: d,
dd: pad(d),
ddd: dF.i18n.dayNames[D],
dddd: dF.i18n.dayNames[D + 7],
m: m + 1,
mm: pad(m + 1),
mmm: dF.i18n.monthNames[m],
mmmm: dF.i18n.monthNames[m + 12],
yy: String(y).slice(2),
yyyy: y,
h: H % 12 || 12,
hh: pad(H % 12 || 12),
H: H,
HH: pad(H),
M: M,
MM: pad(M),
s: s,
ss: pad(s),
l: pad(L, 3),
L: pad(L > 99 ? Math.round(L / 10) : L),
t: H < 12 ? "a" : "p",
tt: H < 12 ? "am" : "pm",
T: H < 12 ? "A" : "P",
TT: H < 12 ? "AM" : "PM",
Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
};
return mask.replace(token, function ($0) {
return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
});
};
}();
// Some common format strings
dateFormat.masks = {
"default": "ddd mmm dd yyyy HH:MM:ss",
shortDate: "m/d/yy",
mediumDate: "mmm d, yyyy",
longDate: "mmmm d, yyyy",
fullDate: "dddd, mmmm d, yyyy",
shortTime: "h:MM TT",
mediumTime: "h:MM:ss TT",
longTime: "h:MM:ss TT Z",
isoDate: "yyyy-mm-dd",
isoTime: "HH:MM:ss",
isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};
// Internationalization strings
dateFormat.i18n = {
dayNames: [
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
],
monthNames: [
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
]
};
// For convenience...
Date.prototype.format = function (mask, utc) {
return dateFormat(this, mask, utc);
};
/**
* Validate date object
* @param {Date} date
* @return {Boolean}
*/
var isValidDate = function(date) {
if( Object.prototype.toString.call(date) === '[object Date]' ) {
return !isNaN(date.getTime());
}
return false;
};
return {
require: 'ngModel',
scope: {
container: "@",
format: "@",
formatSubmit: "@",
monthsFull: "@",
monthsShort: "@",
weekdaysFull: "@",
weekdaysShort: "@",
weekdaysLetter: "@",
firstDay: "=",
disable: "=",
today: "=",
clear: "=",
close: "=",
selectYears: "=",
selectMonths: "=",
onStart: "&",
onRender: "&",
onOpen: "&",
onClose: "&",
onSet: "&",
onStop: "&",
ngReadonly: "=?",
max: "@",
min: "@"
},
link: function (scope, element, attrs, ngModelCtrl) {
ngModelCtrl.$formatters.unshift(function (modelValue) {
if (modelValue) {
var date = new Date(modelValue);
return (angular.isDefined(scope.format)) ? date.format(scope.format) : date.format('d mmmm, yyyy');
}
return null;
});
var monthsFull = (angular.isDefined(scope.monthsFull)) ? scope.$eval(scope.monthsFull) : undefined,
monthsShort = (angular.isDefined(scope.monthsShort)) ? scope.$eval(scope.monthsShort) : undefined,
weekdaysFull = (angular.isDefined(scope.weekdaysFull)) ? scope.$eval(scope.weekdaysFull) : undefined,
weekdaysShort = (angular.isDefined(scope.weekdaysShort)) ? scope.$eval(scope.weekdaysShort) : undefined,
weekdaysLetter = (angular.isDefined(scope.weekdaysLetter)) ? scope.$eval(scope.weekdaysLetter) : undefined;
$compile(element.contents())(scope);
if (!(scope.ngReadonly)) {
$timeout(function () {
var options = {
container : scope.container,
format: (angular.isDefined(scope.format)) ? scope.format : undefined,
formatSubmit: (angular.isDefined(scope.formatSubmit)) ? scope.formatSubmit : undefined,
monthsFull: (angular.isDefined(monthsFull)) ? monthsFull : undefined,
monthsShort: (angular.isDefined(monthsShort)) ? monthsShort : undefined,
weekdaysFull: (angular.isDefined(weekdaysFull)) ? weekdaysFull : undefined,
weekdaysShort: (angular.isDefined(weekdaysShort)) ? weekdaysShort : undefined,
weekdaysLetter: (angular.isDefined(weekdaysLetter)) ? weekdaysLetter : undefined,
firstDay: (angular.isDefined(scope.firstDay)) ? scope.firstDay : 0,
disable: (angular.isDefined(scope.disable)) ? scope.disable : undefined,
today: (angular.isDefined(scope.today)) ? scope.today : undefined,
clear: (angular.isDefined(scope.clear)) ? scope.clear : undefined,
close: (angular.isDefined(scope.close)) ? scope.close : undefined,
selectYears: (angular.isDefined(scope.selectYears)) ? scope.selectYears : undefined,
selectMonths: (angular.isDefined(scope.selectMonths)) ? scope.selectMonths : undefined,
onStart: (angular.isDefined(scope.onStart)) ? function(){ scope.onStart(); } : undefined,
onRender: (angular.isDefined(scope.onRender)) ? function(){ scope.onRender(); } : undefined,
onOpen: (angular.isDefined(scope.onOpen)) ? function(){ scope.onOpen(); } : undefined,
onClose: (angular.isDefined(scope.onClose)) ? function(){ scope.onClose(); } : undefined,
onSet: (angular.isDefined(scope.onSet)) ? function(){ scope.onSet(); } : undefined,
onStop: (angular.isDefined(scope.onStop)) ? function(){ scope.onStop(); } : undefined
};
if (!scope.container) {
delete options.container;
}
var pickadateInput = element.pickadate(options);
//pickadate API
var picker = pickadateInput.pickadate('picker');
//watcher of min, max, and disabled dates
scope.$watch('max', function(newMax) {
if( picker ) {
var maxDate = new Date(newMax);
picker.set({max: isValidDate(maxDate) ? maxDate : false});
}
});
scope.$watch('min', function(newMin) {
if( picker ) {
var minDate = new Date(newMin);
picker.set({min: isValidDate(minDate) ? minDate : false});
}
});
scope.$watch('disable', function(newDisabled) {
if( picker ) {
var disabledDates = angular.isDefined(newDisabled) && angular.isArray(newDisabled) ? newDisabled : false;
picker.set({disable: disabledDates});
}
});
});
}
}
};
}]);
/**
* time-picker directive
* Example:
*/
angular.module("ui.materialize.input_clock", [])
.directive('inputClock', [function () {
return {
restrict: 'A',
scope: {
default: "@",
fromnow: "=?",
donetext: "@",
autoclose: "=?",
ampmclickable: "=?",
darktheme: "=?",
twelvehour: "=?",
vibrate: "=?"
},
link: function (scope, element) {
$(element).addClass("timepicker");
if (!(scope.ngReadonly)) {
element.pickatime({
default: (angular.isDefined(scope.default)) ? scope.default : '',
fromnow: (angular.isDefined(scope.fromnow)) ? scope.fromnow : 0,
donetext: (angular.isDefined(scope.donetext)) ? scope.donetext : 'Done',
autoclose: (angular.isDefined(scope.autoclose)) ? scope.autoclose : false,
ampmclickable: (angular.isDefined(scope.ampmclickable)) ? scope.ampmclickable : false,
darktheme: (angular.isDefined(scope.darktheme)) ? scope.darktheme : false,
twelvehour: (angular.isDefined(scope.twelvehour)) ? scope.twelvehour : true,
vibrate: (angular.isDefined(scope.vibrate)) ? scope.vibrate : true
});
}
}
};
}]);
/**
* Example:
* ul-class could be either an object or a string
*
* Based on https://github.com/brantwills/Angular-Paging
*/
angular.module("ui.materialize.pagination", [])
.directive('pagination', ["$sce", function ($sce) {
// Assign null-able scope values from settings
function setScopeValues(scope, attrs) {
scope.List = [];
scope.Hide = false;
scope.page = parseInt(scope.page) || 1;
scope.total = parseInt(scope.total) || 0;
scope.dots = scope.dots || '...';
scope.ulClass = scope.ulClass || attrs.ulClass || 'pagination';
scope.adjacent = parseInt(scope.adjacent) || 2;
scope.activeClass = 'active';
scope.disabledClass = 'disabled';
scope.scrollTop = scope.$eval(attrs.scrollTop);
scope.hideIfEmpty = scope.$eval(attrs.hideIfEmpty);
scope.showPrevNext = scope.$eval(attrs.showPrevNext);
scope.useSimplePrevNext = scope.$eval(attrs.useSimplePrevNext);
}
// Validate and clean up any scope values
// This happens after we have set the
// scope values
function validateScopeValues(scope, pageCount) {
// Block where the page is larger than the pageCount
if (scope.page > pageCount) {
scope.page = pageCount;
}
// Block where the page is less than 0
if (scope.page <= 0) {
scope.page = 1;
}
// Block where adjacent value is 0 or below
if (scope.adjacent <= 0) {
scope.adjacent = 2;
}
// Hide from page if we have 1 or less pages
// if directed to hide empty
if (pageCount <= 1) {
scope.Hide = scope.hideIfEmpty;
}
}
// Internal Pagination Click Action
function internalAction(scope, page) {
page = page.valueOf();
// Block clicks we try to load the active page
if (scope.page == page) {
return;
}
// Update the page in scope and fire any paging actions
scope.page = page;
scope.paginationAction({
page: page
});
// If allowed scroll up to the top of the page
if (scope.scrollTop) {
scrollTo(0, 0);
}
}
// Add Range of Numbers
function addRange(start, finish, scope) {
var i = 0;
for (i = start; i <= finish; i++) {
var item = {
value: $sce.trustAsHtml(i.toString()),
liClass: scope.page == i ? scope.activeClass : 'waves-effect',
action: function() {
internalAction(scope, this.value);
}
};
scope.List.push(item);
}
}
// Add Dots ie: 1 2 [...] 10 11 12 [...] 56 57
function addDots(scope) {
scope.List.push({
value: $sce.trustAsHtml(scope.dots)
});
}
// Add First Pages
function addFirst(scope, next) {
addRange(1, 2, scope);
// We ignore dots if the next value is 3
// ie: 1 2 [...] 3 4 5 becomes just 1 2 3 4 5
if (next != 3) {
addDots(scope);
}
}
/**
* Add the first, previous, next, and last buttons if desired
* The logic is defined by the mode of interest
* This method will simply return if the scope.showPrevNext is false
* This method will simply return if there are no pages to display
*
* @param {Object} scope - The local directive scope object
* @param {int} pageCount - The last page number or total page count
* @param {string} mode - The mode of interest either prev or last
*/
function addPrevNext(scope, pageCount, mode){
// Ignore if we are not showing
// or there are no pages to display
if (!scope.showPrevNext || pageCount < 1) { return; }
// Local variables to help determine logic
var disabled, alpha, beta;
// Determine logic based on the mode of interest
// Calculate the previous / next page and if the click actions are allowed
if(mode === 'prev') {
disabled = scope.page - 1 <= 0;
var prevPage = scope.page - 1 <= 0 ? 1 : scope.page - 1;
if (scope.useSimplePrevNext) {
alpha = {value: "<<", title: 'First Page', page: 1};
beta = {value: "<", title: 'Previous Page', page: prevPage };
} else {
alpha = {value: "first_page", title: 'First Page', page: 1};
beta = {value: "chevron_left", title: 'Previous Page', page: prevPage };
}
} else {
disabled = scope.page + 1 > pageCount;
var nextPage = scope.page + 1 >= pageCount ? pageCount : scope.page + 1;
if (scope.useSimplePrevNext) {
alpha = { value : ">", title: 'Next Page', page: nextPage };
beta = { value: ">>", title: 'Last Page', page: pageCount };
} else {
alpha = { value : "chevron_right", title: 'Next Page', page: nextPage };
beta = { value: "last_page", title: 'Last Page', page: pageCount };
}
}
// Create the Add Item Function
var addItem = function(item, disabled){
scope.List.push({
value: $sce.trustAsHtml(item.value),
title: item.title,
liClass: disabled ? scope.disabledClass : '',
action: function(){
if(!disabled) {
internalAction(scope, item.page);
}
}
});
};
// Add our items
addItem(alpha, disabled);
addItem(beta, disabled);
}
function addLast(pageCount, scope, prev) {
// We ignore dots if the previous value is one less that our start range
// ie: 1 2 3 4 [...] 5 6 becomes just 1 2 3 4 5 6
if (prev != pageCount -2) {
addDots(scope);
}
addRange(pageCount -1, pageCount, scope);
}
// Main build function
function build(scope, attrs) {
// Block divide by 0 and empty page size
if (!scope.pageSize || scope.pageSize < 0)
{
return;
}
// Assign scope values
setScopeValues(scope, attrs);
// local variables
var start,
size = scope.adjacent * 2,
pageCount = Math.ceil(scope.total / scope.pageSize);
// Validation Scope
validateScopeValues(scope, pageCount);
// Add the Next and Previous buttons to our list
addPrevNext(scope, pageCount, 'prev');
if (pageCount < (5 + size)) {
start = 1;
addRange(start, pageCount, scope);
} else {
var finish;
if (scope.page <= (1 + size)) {
start = 1;
finish = 2 + size + (scope.adjacent - 1);
addRange(start, finish, scope);
addLast(pageCount, scope, finish);
} else if (pageCount - size > scope.page && scope.page > size) {
start = scope.page - scope.adjacent;
finish = scope.page + scope.adjacent;
addFirst(scope, start);
addRange(start, finish, scope);
addLast(pageCount, scope, finish);
} else {
start = pageCount - (1 + size + (scope.adjacent - 1));
finish = pageCount;
addFirst(scope, start);
addRange(start, finish, scope);
}
}
addPrevNext(scope, pageCount, 'next');
}
return {
restrict: 'EA',
scope: {
page: '=',
pageSize: '=',
total: '=',
dots: '@',
hideIfEmpty: '@',
adjacent: '@',
scrollTop: '@',
showPrevNext: '@',
useSimplePrevNext: '@',
paginationAction: '&',
ulClass: '=?'
},
template:
'',
link: function (scope, element, attrs) {
// Hook in our watched items
scope.$watchCollection('[page, total, pageSize]', function () {
build(scope, attrs);
});
}
};
}]);
/* example usage:
show Modal
Modal Header
A bunch of text
*/
angular.module("ui.materialize.modal", [])
.directive("modal", ["$compile", "$timeout", function ($compile, $timeout) {
return {
scope: {
dismissible: "=",
opacity: "@",
inDuration: "@",
outDuration: "@",
ready: '&?',
complete: '&?',
open: '=?',
enableTabs: '@?'
},
link: function (scope, element, attrs) {
$timeout(function () {
var modalEl = $(attrs.href ? attrs.href : '#' + attrs.target);
$compile(element.contents())(scope);
var complete = function () {
angular.isFunction(scope.complete) && scope.$apply(scope.complete);
scope.open = false;
scope.$apply();
};
var ready = function() {
angular.isFunction(scope.ready) && scope.$apply(scope.ready);
// Need to keep open boolean in sync.
scope.open = true;
scope.$apply();
// If tab support is enabled we need to re-init the tabs
// See https://github.com/Dogfalo/materialize/issues/1634
if (scope.enableTabs) {
modalEl.find('ul.tabs').tabs();
}
};
var options = {
dismissible: (angular.isDefined(scope.dismissible)) ? scope.dismissible : undefined,
opacity: (angular.isDefined(scope.opacity)) ? scope.opacity : undefined,
in_duration: (angular.isDefined(scope.inDuration)) ? scope.inDuration : undefined,
out_duration: (angular.isDefined(scope.outDuration)) ? scope.outDuration : undefined,
ready: ready,
complete: complete,
};
modalEl.modal(options);
element.modal(options);
// Setup watch for opening / closing modal programatically.
if (angular.isDefined(attrs.open) && modalEl.length > 0) {
scope.$watch('open', function(value, lastValue) {
if (!angular.isDefined(value)) { return; }
(value === true) ? modalEl.modal('open') : modalEl.modal('close');
});
}
});
}
};
}]);
/* example usage:
Hover me!
*/
angular.module("ui.materialize.tooltipped", [])
.directive("tooltipped", ["$compile", "$timeout", function ($compile, $timeout) {
return {
restrict: "A",
link: function (scope, element, attrs) {
var rmDestroyListener = Function.prototype; //assigning to noop
function init() {
element.addClass("tooltipped");
$compile(element.contents())(scope);
$timeout(function () {
// https://github.com/Dogfalo/materialize/issues/3546
// if element.addClass("tooltipped") would not be executed, then probably this would not be needed
if (element.attr('data-tooltip-id')){
element.tooltip('remove');
}
element.tooltip();
});
rmDestroyListener = scope.$on('$destroy', function () {
element.tooltip("remove");
});
}
attrs.$observe('tooltipped', function (value) {
if (value === 'false' && rmDestroyListener !== Function.prototype) {
element.tooltip("remove");
rmDestroyListener();
rmDestroyListener = Function.prototype;
} else if (value !== 'false' && rmDestroyListener === Function.prototype) {
init();
}
});
if (attrs.tooltipped !== 'false') {
init();
}
// just to be sure, that tooltip is removed when somehow element is destroyed, but the parent scope is not
element.on('$destroy', function() {
element.tooltip("remove");
});
}
};
}]);
/* example usage:
*/
angular.module("ui.materialize.materialboxed", [])
.directive("materialboxed", ["$timeout", function($timeout){
return {
restrict: 'A',
link: function(scope, element, attrs) {
$timeout(function(){
element.materialbox();
});
}
};
}]);
/* example usage:
In controller:
$scope.value = [30];
$scope.value = 30;
$scope.value = [30, 40];
(green) bar beetwen one handle
(green) bar beetwen handles
*/
angular.module("ui.materialize.nouislider", [])
.directive("nouislider", ["$timeout", function($timeout){
return {
restrict: 'A',
scope: {
ngModel: '=',
min: '@',
max: '@',
step: '@?',
connect: '@?',
tooltips: '@?',
behaviour: '@?'
},
link: function (scope, element, attrs) {
var modelIsArray = false;
var watchNgModel = scope.$watch('ngModel', function(newValue) {
if (newValue !== undefined) {
createNoUiSlider();
watchNgModel();
}
});
element[0].noUiSlider.on('update', function(values, input) {
$timeout(function() {
scope.ngModel = modelIsArray ? values : values[0];
});
});
function createNoUiSlider() {
if (angular.isArray(scope.ngModel)) {
modelIsArray = true;
}
noUiSlider.create(element[0], {
start: scope.ngModel || 0,
step: parseFloat(scope.step || 1),
tooltips: angular.isDefined(scope.tooltips) ? scope.tooltips : undefined,
connect: angular.isDefined(scope.connect) ? scope.connect : [false, false],
behaviour: angular.isDefined(scope.behaviour) ? scope.behaviour : undefined,
range: {
'min': parseFloat(scope.min || 0),
'max': parseFloat(scope.max || 100),
},
format: {
to: function (number) {
return Math.round(number * 100) / 100;
},
from: function (number) {
return Number(number);
}
}
});
function getConnection(value) {
value.toLowerCase();
if ('true' === value || 'false' === value) {
return JSON.parse(value);
}
return value;
}
};
}
};
}]);
}(angular));