drowl_paragraphs_bs-1.x-dev/modules/drowl_paragraphs_bs_type_score/js/drowl_paragraphs_bs_type_score.js
modules/drowl_paragraphs_bs_type_score/js/drowl_paragraphs_bs_type_score.js
/**
* @file
* DROWL Paragraphs for Bootstrap Type "Score" initialization
*
*/
(function ($, Drupal) {
Drupal.behaviors.drowl_paragraphs_bs_type_score = {
attach: function (context, settings) {
function unquote(string) {
return string.replace(/['"]+/g, "");
}
function rgbaToRgb(rgbaString) {
let rgbaArr = rgbaString
.replace(/^(rgb|rgba)\(/, "")
.replace(/\)$/, "")
.replace(/\s/g, "")
.split(",");
return "rgb(" + rgbaArr[0] + "," + rgbaArr[1] + "," + rgbaArr[2] + ")";
}
function observeScore($scoreWrapper, bar, scoreStartRate, scoreEndRate) {
var scoreObserver = new IntersectionObserver(function (score) {
$(score).each(function () {
if ($(this)[0].intersectionRatio > 0) {
if (scoreStartRate > 0) {
// @todo: LOW PRIO - delay bar.animate in this case? looks a little weird if it first jumps to the start value and then directly animates to the target value
bar.set(scoreStartRate);
}
bar.animate(scoreEndRate); // Number from 0.0 to 1.0
} else {
// Reset to origin value
if (scoreStartRate > 0) {
bar.set(scoreStartRate);
} else {
bar.animate(0.0);
}
}
});
});
// Start observing
scoreObserver.observe($scoreWrapper[0]);
}
$(".score:not(.processed)", context).each(function () {
let $scoreWrapper = $(this);
let $scoreProgressbar = $(this).children(".score__progressbar:first");
let scoreProgressbarId = $scoreProgressbar.attr("id");
let scoreType = $scoreWrapper.data("score-type");
let scoreStart = $scoreWrapper.data("score-start");
let scoreEnd = $scoreWrapper.data("score-end");
let scoreMax = $scoreWrapper.data("score-max");
// Ensure scoreMax is not zero (devision by zero error)
if (scoreMax <= 0) {
scoreMax = 1;
}
let scoreTrailWidth = $scoreWrapper.data("score-trail-width");
let scoreStrokeWidth = $scoreWrapper.data("score-stroke-width");
let scoreStrokeWidthStart = $scoreWrapper.data(
"score-stroke-width-start"
);
let scoreAnimationDuration = $scoreWrapper.data(
"score-animation-duration"
);
let scoreAnimationEasing = $scoreWrapper.data("score-animation-easing");
let scorePrefix = $scoreWrapper.data("score-prefix");
let scoreSuffix = $scoreWrapper.data("score-suffix");
let scoreMaxPrefix = $scoreWrapper.data("score-max-prefix");
let scoreMaxSuffix = $scoreWrapper.data("score-max-suffix");
let scoreValueDisplay = $scoreWrapper.data("score-value-display");
let $scoreIcon = $scoreWrapper.children(".score__icon:first");
// Calculate percentages from absolute numbers for the animate() values
let scoreStartRate = Number((scoreStart / scoreMax).toFixed(2));
let scoreEndRate = Number((scoreEnd / scoreMax).toFixed(2));
// Get the colors from css variables
let scoreLineColor = unquote(
getComputedStyle($scoreWrapper[0]).getPropertyValue("--line-color")
);
let scoreBarColor = unquote(
getComputedStyle($scoreWrapper[0]).getPropertyValue("--bar-color")
);
let scoreBarEndColor = unquote(
getComputedStyle($scoreWrapper[0]).getPropertyValue("--bar-end-color")
);
// @todo: Temporary fix for RGBA values - not supported in this old shifty (dependency) release
// see: https://github.com/kimmobrunfeldt/progressbar.js/issues/296
if(!scoreLineColor.length){
scoreLineColor = "#0d6efd";
}else if (scoreLineColor.startsWith("rgba")) {
scoreLineColor = rgbaToRgb(scoreLineColor);
}
if(!scoreBarColor.length){
scoreBarColor = "#0d6efd";
}else if (scoreBarColor.startsWith("rgba")) {
scoreBarColor = rgbaToRgb(scoreBarColor);
}
if(!scoreBarEndColor.length){
scoreBarEndColor = "#0d6efd";
}else if (scoreBarEndColor.startsWith("rgba")) {
scoreBarEndColor = rgbaToRgb(scoreBarEndColor);
}
// Prepare Progressbar Contents Markup
let scoreIconMarkup = $scoreIcon.length
? `<span class="score__progressbar-icon">${$scoreIcon.html()}</span>`
: "";
let scoreDeviderMarkup =
scoreEnd && scoreValueDisplay == "current-and-target"
? `<span class="score__progressbar-devider"></span>`
: "";
let scorePrefixMarkup = scorePrefix
? `<span class="score__progressbar-prefix">${scorePrefix}</span>`
: "";
let scoreSuffixMarkup = scoreSuffix
? `<span class="score__progressbar-suffix">${scoreSuffix}</span>`
: "";
let scoreMaxPrefixMarkup =
scoreMax && scoreMaxPrefix && scoreValueDisplay == "current-and-target"
? `<span class="score__progressbar-max-prefix">${scoreMaxPrefix}</span>`
: "";
let scoreMaxSuffixMarkup =
scoreMax && scoreMaxSuffix && scoreValueDisplay == "current-and-target"
? `<span class="score__progressbar-max-suffix">${scoreMaxSuffix}</span>`
: "";
let scoreMaxValueMarkup =
scoreMax && scoreValueDisplay == "current-and-target"
? `<span class="score__progressbar-max-value">${Math.round(scoreMax)}</span>`
: "";
// Init progressbar.js
let bar;
console.log(scoreType);
if (scoreType == "semicircle") {
bar = new ProgressBar.SemiCircle("#" + scoreProgressbarId, {
// strokeWidth has to be the same size as the maximum width to prevent clipping
strokeWidth: scoreStrokeWidth,
trailWidth: scoreTrailWidth,
trailColor: scoreLineColor,
easing: scoreAnimationEasing,
duration: scoreAnimationDuration,
svgStyle: null,
text: {
className: "score__progressbar-content",
autoStyleContainer: false,
style: null,
},
from: {
color: scoreBarColor,
width: scoreStrokeWidthStart,
},
to: {
color: scoreBarEndColor.length ? scoreBarEndColor : scoreBarColor,
width: scoreStrokeWidth,
},
// Set default step function for all animate calls
step: (state, bar) => {
let value = Math.round(bar.value() * scoreMax);
bar.path.setAttribute("stroke", state.color);
bar.path.setAttribute("stroke-width", state.width);
bar.setText(
`${scoreIconMarkup + scorePrefixMarkup}<span class="score__progressbar-current">${
value === 0 ? 0 : value
}</span>${
scoreSuffixMarkup +
scoreDeviderMarkup +
scoreMaxPrefixMarkup +
scoreMaxValueMarkup +
scoreMaxSuffixMarkup
}`
);
},
});
} else if (scoreType == "line") {
bar = new ProgressBar.Line("#" + scoreProgressbarId, {
// strokeWidth has to be the same size as the maximum width to prevent clipping
strokeWidth: scoreStrokeWidth,
trailWidth: scoreTrailWidth,
trailColor: scoreLineColor,
easing: scoreAnimationEasing,
duration: scoreAnimationDuration,
svgStyle: null,
text: {
className: "score__progressbar-content",
autoStyleContainer: false,
style: null,
},
from: {
color: scoreBarColor,
width: scoreStrokeWidthStart,
},
to: {
color: scoreBarEndColor.length ? scoreBarEndColor : scoreBarColor,
width: scoreStrokeWidth,
},
step: (state, bar) => {
let value = Math.round(bar.value() * scoreMax);
bar.path.setAttribute("stroke", state.color);
bar.path.setAttribute("stroke-width", state.width);
bar.setText(
`${scoreIconMarkup + scorePrefixMarkup}<span class="score__progressbar-current">${
value === 0 ? 0 : value
}</span>${
scoreSuffixMarkup +
scoreDeviderMarkup +
scoreMaxPrefixMarkup +
scoreMaxValueMarkup +
scoreMaxSuffixMarkup
}`
);
},
});
} else if (scoreType == "circle") {
bar = new ProgressBar.Circle("#" + scoreProgressbarId, {
// strokeWidth has to be the same size as the maximum width to prevent clipping
strokeWidth: scoreStrokeWidth,
trailWidth: scoreTrailWidth,
trailColor: scoreLineColor,
easing: scoreAnimationEasing,
duration: scoreAnimationDuration,
svgStyle: null,
text: {
className: "score__progressbar-content",
autoStyleContainer: false,
style: null,
},
from: {
color: scoreBarColor,
width: scoreStrokeWidthStart,
},
to: {
color: scoreBarEndColor.length ? scoreBarEndColor : scoreBarColor,
width: scoreStrokeWidth,
},
// Set default step function for all animate calls
step: function (state, circle) {
let value = Math.round(circle.value() * scoreMax);
circle.path.setAttribute("stroke", state.color);
circle.path.setAttribute("stroke-width", state.width);
circle.setText(
`${scoreIconMarkup + scorePrefixMarkup}<span class="score__progressbar-current">${
value === 0 ? 0 : value
}</span>${
scoreSuffixMarkup +
scoreDeviderMarkup +
scoreMaxPrefixMarkup +
scoreMaxValueMarkup +
scoreMaxSuffixMarkup
}`
);
},
});
}
if(bar){
// Initialize the scroll observer
observeScore($scoreWrapper, bar, scoreStartRate, scoreEndRate);
// Fix ajax issues
$scoreWrapper.addClass("processed");
}
});
},
};
})(jQuery, Drupal);
