diff --git a/Gruntfile.js b/Gruntfile.js
index a59c033fb..418ba7ce9 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -62,6 +62,16 @@ module.exports = function (grunt) {
files: {
'app/assets/admin/js/admin.min.js': ['app/assets/admin/js/scripts.js']
}
+ },
+ godam: {
+ files: {
+ 'app/assets/js/godam-integration.min.js': ['app/assets/js/godam-integration.js']
+ }
+ },
+ godam_ajax_refresh: {
+ files: {
+ 'app/assets/js/godam-ajax-refresh.min.js': ['app/assets/js/godam-ajax-refresh.js']
+ }
}
}
});
diff --git a/README.md b/README.md
index c58967c00..70ff3f11c 100644
--- a/README.md
+++ b/README.md
@@ -151,6 +151,18 @@ https://www.youtube.com/watch?v=dJrykKQGDcs
## Changelog ##
+### 4.7.0
+
+* ENHANCEMENTS
+ * Added integration with GoDAM plugin's video player.
+ * Enabled support for GoDAM video player in rtMedia media gallery, BuddyPress activity stream, groups, and forums.
+ * Improved handling of player enqueue conditions based on GoDAM plugin status.
+ * Refined script loading to ensure compatibility across WordPress, BuddyPress, and rtMedia components.
+
+* FIXED
+ * Prevented conflicts with `mediaelement.js` when GoDAM plugin is active.
+ * Deregistered conflicting scripts to ensure seamless fallback and prevent duplication in player initialization.
+
### 4.6.23
* Fixed
diff --git a/app/assets/js/godam-ajax-refresh.js b/app/assets/js/godam-ajax-refresh.js
new file mode 100644
index 000000000..52ddada66
--- /dev/null
+++ b/app/assets/js/godam-ajax-refresh.js
@@ -0,0 +1,275 @@
+// Enhanced AJAX function with better error handling and retry logic
+function refreshSingleComment(commentId, node) {
+ // Validation checks
+ if (!commentId || !node) {
+ return;
+ }
+
+ // Check if GodamAjax object exists
+ if (typeof GodamAjax === 'undefined' || !GodamAjax.ajax_url || !GodamAjax.nonce) {
+ return;
+ }
+
+ // Check if node is still in the DOM
+ if (!document.contains(node)) {
+ return;
+ }
+
+ // Prevent duplicate requests
+ if (node.classList.contains('refreshing')) {
+ return;
+ }
+ node.classList.add('refreshing');
+
+ // Create AbortController for timeout handling
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => {
+ controller.abort();
+ }, 15000); // 15 second timeout
+
+ fetch(GodamAjax.ajax_url, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ body: new URLSearchParams({
+ action: 'get_single_activity_comment_html',
+ comment_id: commentId,
+ nonce: GodamAjax.nonce,
+ }),
+ signal: controller.signal
+ })
+ .then(response => {
+ clearTimeout(timeoutId);
+
+ // Check if response is ok
+ if (!response.ok) {
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
+ }
+
+ // Check content type
+ const contentType = response.headers.get('content-type');
+ if (!contentType || !contentType.includes('application/json')) {
+ throw new Error('Server returned non-JSON response');
+ }
+
+ return response.json();
+ })
+ .then(data => {
+ if (data && data.success && data.data && data.data.html) {
+ // Success - handle the response
+ handleSuccessfulResponse(data, commentId, node);
+ } else {
+ // AJAX returned error
+ const errorMsg = data && data.data ? data.data : 'Unknown AJAX error';
+ console.error('AJAX error:', errorMsg);
+
+ // Optional: Retry once after a delay
+ setTimeout(() => {
+ retryRefreshComment(commentId, node, 1);
+ }, 2000);
+ }
+ })
+ .catch(error => {
+ clearTimeout(timeoutId);
+ console.error('Fetch error:', error);
+
+ // Handle specific error types
+ if (error.name === 'AbortError') {
+ console.error('Request timed out');
+ } else if (error.message.includes('Failed to fetch')) {
+ console.error('Network error - possible connectivity issue');
+ // Retry after network error
+ setTimeout(() => {
+ retryRefreshComment(commentId, node, 1);
+ }, 3000);
+ }
+ })
+ .finally(() => {
+ clearTimeout(timeoutId);
+ // Always remove refreshing class
+ if (document.contains(node)) {
+ node.classList.remove('refreshing');
+ }
+ });
+}
+
+// Retry function with exponential backoff
+function retryRefreshComment(commentId, node, attempt = 1) {
+ const maxRetries = 2;
+
+ if (attempt > maxRetries) {
+ console.error(`Failed to refresh comment ${commentId} after ${maxRetries} retries`);
+ return;
+ }
+
+ // Check if node still exists
+ if (!document.contains(node)) {
+ return;
+ }
+
+ // Exponential backoff delay
+ const delay = Math.pow(2, attempt) * 1000; // 2s, 4s, 8s...
+
+ setTimeout(() => {
+ // Remove any existing refreshing class
+ node.classList.remove('refreshing');
+
+ // Try again with modified fetch (more conservative approach)
+ fetch(GodamAjax.ajax_url, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'Cache-Control': 'no-cache',
+ },
+ body: new URLSearchParams({
+ action: 'get_single_activity_comment_html',
+ comment_id: commentId,
+ nonce: GodamAjax.nonce,
+ retry: attempt.toString()
+ }),
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data && data.success && data.data && data.data.html) {
+ handleSuccessfulResponse(data, commentId, node);
+ } else {
+ // Retry again if not max attempts
+ if (attempt < maxRetries) {
+ retryRefreshComment(commentId, node, attempt + 1);
+ }
+ }
+ })
+ .catch(error => {
+ console.error(`Retry ${attempt} failed:`, error);
+ if (attempt < maxRetries) {
+ retryRefreshComment(commentId, node, attempt + 1);
+ }
+ });
+ }, delay);
+}
+
+// Handle successful AJAX response
+function handleSuccessfulResponse(data, commentId, node) {
+ try {
+ // Find parent activity more safely
+ const activityItem = node.closest('.activity-item');
+ if (!activityItem) {
+ console.error('Could not find parent activity item');
+ return;
+ }
+
+ const parentActivityId = activityItem.id.replace('activity-', '');
+
+ // Locate comment container
+ let commentList = document.querySelector(`#activity-${parentActivityId} .activity-comments`);
+ if (!commentList) {
+ commentList = document.createElement('ul');
+ commentList.classList.add('activity-comments');
+ activityItem.appendChild(commentList);
+ }
+
+ // Create temporary container for HTML parsing
+ const tempDiv = document.createElement('div');
+ tempDiv.innerHTML = data.data.html.trim();
+ const newCommentNode = tempDiv.firstElementChild;
+
+ if (newCommentNode) {
+ // Insert new comment
+ commentList.appendChild(newCommentNode);
+
+ // Remove old node safely
+ if (node.parentNode && document.contains(node)) {
+ node.parentNode.removeChild(node);
+ }
+
+ // Initialize GODAMPlayer if available
+ if (typeof GODAMPlayer === 'function') {
+ try {
+ GODAMPlayer(newCommentNode);
+ } catch (playerError) {
+ console.error('GODAMPlayer initialization failed:', playerError);
+ }
+ }
+
+ // Dispatch custom event for other scripts
+ document.dispatchEvent(new CustomEvent('commentRefreshed', {
+ detail: { commentId, node: newCommentNode }
+ }));
+
+ } else {
+ console.error('No valid comment node found in response HTML');
+ }
+ } catch (error) {
+ console.error('Error handling successful response:', error);
+ }
+}
+
+// Enhanced DOM observer with debouncing
+document.addEventListener('DOMContentLoaded', () => {
+ const commentsContainers = document.querySelectorAll('.activity-comments');
+
+ if (commentsContainers.length === 0) {
+ return;
+ }
+
+ // Debounce function to prevent rapid-fire calls
+ function debounce(func, wait) {
+ let timeout;
+ return function executedFunction(...args) {
+ const later = () => {
+ clearTimeout(timeout);
+ func(...args);
+ };
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ };
+ }
+
+ commentsContainers.forEach((container) => {
+ // Initialize GODAMPlayer on existing comments
+ if (typeof GODAMPlayer === 'function') {
+ try {
+ GODAMPlayer(container);
+ } catch (error) {
+ console.error('GODAMPlayer initialization failed:', error);
+ }
+ }
+
+ // Debounced mutation handler
+ const debouncedHandler = debounce((mutations) => {
+ mutations.forEach((mutation) => {
+ mutation.addedNodes.forEach((node) => {
+ if (node.nodeType === 1 && node.matches && node.matches('li[id^="acomment-"]')) {
+ // Initialize GODAMPlayer first
+ if (typeof GODAMPlayer === 'function') {
+ try {
+ GODAMPlayer(node);
+ } catch (error) {
+ console.error('GODAMPlayer initialization failed:', error);
+ }
+ }
+
+ // Extract comment ID and refresh with delay
+ const commentId = node.id.replace('acomment-', '');
+
+ // Add longer delay to ensure DOM stability
+ setTimeout(() => {
+ if (document.contains(node)) {
+ refreshSingleComment(commentId, node);
+ }
+ }, 250);
+ }
+ });
+ });
+ }, 100); // 100ms debounce
+
+ // Create observer
+ const observer = new MutationObserver(debouncedHandler);
+
+ observer.observe(container, {
+ childList: true,
+ subtree: true
+ });
+ });
+});
diff --git a/app/assets/js/godam-ajax-refresh.min.js b/app/assets/js/godam-ajax-refresh.min.js
new file mode 100644
index 000000000..25ba334bc
--- /dev/null
+++ b/app/assets/js/godam-ajax-refresh.min.js
@@ -0,0 +1 @@
+function refreshSingleComment(e,t){if(!e||!t)return;if("undefined"==typeof GodamAjax||!GodamAjax.ajax_url||!GodamAjax.nonce)return;if(!document.contains(t))return;if(t.classList.contains("refreshing"))return;t.classList.add("refreshing");const o=new AbortController,n=setTimeout((()=>{o.abort()}),15e3);fetch(GodamAjax.ajax_url,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({action:"get_single_activity_comment_html",comment_id:e,nonce:GodamAjax.nonce}),signal:o.signal}).then((e=>{if(clearTimeout(n),!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);const t=e.headers.get("content-type");if(!t||!t.includes("application/json"))throw new Error("Server returned non-JSON response");return e.json()})).then((o=>{if(o&&o.success&&o.data&&o.data.html)handleSuccessfulResponse(o,e,t);else{const n=o&&o.data?o.data:"Unknown AJAX error";console.error("AJAX error:",n),setTimeout((()=>{retryRefreshComment(e,t,1)}),2e3)}})).catch((o=>{clearTimeout(n),console.error("Fetch error:",o),"AbortError"===o.name?console.error("Request timed out"):o.message.includes("Failed to fetch")&&(console.error("Network error - possible connectivity issue"),setTimeout((()=>{retryRefreshComment(e,t,1)}),3e3))})).finally((()=>{clearTimeout(n),document.contains(t)&&t.classList.remove("refreshing")}))}function retryRefreshComment(e,t,o=1){if(o>2)return void console.error(`Failed to refresh comment ${e} after 2 retries`);if(!document.contains(t))return;const n=1e3*Math.pow(2,o);setTimeout((()=>{t.classList.remove("refreshing"),fetch(GodamAjax.ajax_url,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded","Cache-Control":"no-cache"},body:new URLSearchParams({action:"get_single_activity_comment_html",comment_id:e,nonce:GodamAjax.nonce,retry:o.toString()})}).then((e=>e.json())).then((n=>{n&&n.success&&n.data&&n.data.html?handleSuccessfulResponse(n,e,t):o<2&&retryRefreshComment(e,t,o+1)})).catch((n=>{console.error(`Retry ${o} failed:`,n),o<2&&retryRefreshComment(e,t,o+1)}))}),n)}function handleSuccessfulResponse(e,t,o){try{const n=o.closest(".activity-item");if(!n)return void console.error("Could not find parent activity item");const r=n.id.replace("activity-","");let a=document.querySelector(`#activity-${r} .activity-comments`);a||(a=document.createElement("ul"),a.classList.add("activity-comments"),n.appendChild(a));const c=document.createElement("div");c.innerHTML=e.data.html.trim();const i=c.firstElementChild;if(i){if(a.appendChild(i),o.parentNode&&document.contains(o)&&o.parentNode.removeChild(o),"function"==typeof GODAMPlayer)try{GODAMPlayer(i)}catch(e){console.error("GODAMPlayer initialization failed:",e)}document.dispatchEvent(new CustomEvent("commentRefreshed",{detail:{commentId:t,node:i}}))}else console.error("No valid comment node found in response HTML")}catch(e){console.error("Error handling successful response:",e)}}document.addEventListener("DOMContentLoaded",(()=>{const e=document.querySelectorAll(".activity-comments");0!==e.length&&e.forEach((e=>{if("function"==typeof GODAMPlayer)try{GODAMPlayer(e)}catch(e){console.error("GODAMPlayer initialization failed:",e)}const t=function(e,t){let o;return function(...n){clearTimeout(o),o=setTimeout((()=>{clearTimeout(o),e(...n)}),t)}}((e=>{e.forEach((e=>{e.addedNodes.forEach((e=>{if(1===e.nodeType&&e.matches&&e.matches('li[id^="acomment-"]')){if("function"==typeof GODAMPlayer)try{GODAMPlayer(e)}catch(e){console.error("GODAMPlayer initialization failed:",e)}const t=e.id.replace("acomment-","");setTimeout((()=>{document.contains(e)&&refreshSingleComment(t,e)}),250)}}))}))}),100);new MutationObserver(t).observe(e,{childList:!0,subtree:!0})}))}));
\ No newline at end of file
diff --git a/app/assets/js/godam-integration.js b/app/assets/js/godam-integration.js
new file mode 100644
index 000000000..f30b940d6
--- /dev/null
+++ b/app/assets/js/godam-integration.js
@@ -0,0 +1,87 @@
+/**
+ * GODAMPlayer Integration Script
+ *
+ * Initializes GODAMPlayer safely across the site, including:
+ * - Initial load
+ * - Popups using Magnific Popup
+ * - Dynamically added elements (e.g., via BuddyPress activities)
+ *
+ * Ensures robust handling of null or invalid elements and minimizes the risk of runtime errors.
+ */
+
+const safeGODAMPlayer = (element = null) => {
+ try {
+ if (element) {
+ if (element.nodeType === 1 && element.isConnected) {
+ GODAMPlayer(element);
+ } else {
+ GODAMPlayer();
+ }
+ } else {
+ GODAMPlayer();
+ }
+ return true;
+ } catch (error) {
+ return false;
+ }
+};
+
+// Initial load
+safeGODAMPlayer();
+
+// Debounced popup initializer
+let popupInitTimeout = null;
+const initializePopupVideos = () => {
+ clearTimeout(popupInitTimeout);
+ popupInitTimeout = setTimeout(() => {
+ const popupContent = document.querySelector('.mfp-content');
+ if (popupContent) {
+ const videos = popupContent.querySelectorAll('video');
+ if (videos.length > 0) {
+ if (!safeGODAMPlayer(popupContent)) {
+ safeGODAMPlayer();
+ }
+ }
+ }
+ }, 200);
+};
+
+document.addEventListener('DOMContentLoaded', () => {
+ safeGODAMPlayer();
+
+ const observer = new MutationObserver((mutations) => {
+ for (const mutation of mutations) {
+ for (const node of mutation.addedNodes) {
+ if (node.nodeType === 1) {
+ const isPopup = node.classList?.contains('mfp-content') ||
+ node.querySelector?.('.mfp-content');
+ const hasVideos = node.tagName === 'VIDEO' ||
+ node.querySelector?.('video');
+
+ if (isPopup || (hasVideos && node.closest('.mfp-content'))) {
+ initializePopupVideos();
+ }
+
+ if (node.classList?.contains('activity')) {
+ setTimeout(() => safeGODAMPlayer(node), 100);
+ }
+ }
+ }
+ }
+ });
+
+ observer.observe(document.body, {
+ childList: true,
+ subtree: true
+ });
+
+ if (typeof $ !== 'undefined' && $.magnificPopup) {
+ $(document).on('mfpOpen mfpChange', () => {
+ initializePopupVideos();
+ });
+
+ $(document).on('mfpOpen', () => {
+ setTimeout(initializePopupVideos, 500);
+ });
+ }
+});
diff --git a/app/assets/js/godam-integration.min.js b/app/assets/js/godam-integration.min.js
new file mode 100644
index 000000000..6d059872d
--- /dev/null
+++ b/app/assets/js/godam-integration.min.js
@@ -0,0 +1 @@
+const safeGODAMPlayer=(e=null)=>{try{return e&&1===e.nodeType&&e.isConnected?GODAMPlayer(e):GODAMPlayer(),!0}catch(e){return!1}};safeGODAMPlayer();let popupInitTimeout=null;const initializePopupVideos=()=>{clearTimeout(popupInitTimeout),popupInitTimeout=setTimeout((()=>{const e=document.querySelector(".mfp-content");if(e){e.querySelectorAll("video").length>0&&(safeGODAMPlayer(e)||safeGODAMPlayer())}}),200)};document.addEventListener("DOMContentLoaded",(()=>{safeGODAMPlayer();new MutationObserver((e=>{for(const t of e)for(const e of t.addedNodes)if(1===e.nodeType){const t=e.classList?.contains("mfp-content")||e.querySelector?.(".mfp-content"),o="VIDEO"===e.tagName||e.querySelector?.("video");(t||o&&e.closest(".mfp-content"))&&initializePopupVideos(),e.classList?.contains("activity")&&setTimeout((()=>safeGODAMPlayer(e)),100)}})).observe(document.body,{childList:!0,subtree:!0}),"undefined"!=typeof $&&$.magnificPopup&&($(document).on("mfpOpen mfpChange",(()=>{initializePopupVideos()})),$(document).on("mfpOpen",(()=>{setTimeout(initializePopupVideos,500)})))}));
\ No newline at end of file
diff --git a/app/assets/js/rtmedia.min.js b/app/assets/js/rtmedia.min.js
index 7c5ab5084..24b945aa1 100644
--- a/app/assets/js/rtmedia.min.js
+++ b/app/assets/js/rtmedia.min.js
@@ -1,6 +1 @@
-/*!
- * rtMedia JavaScript Library
- * @package rtMedia
- */
-
-var rtMagnificPopup,rtm_masonry_container;!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports?e(require("jquery")):e(window.jQuery||window.Zepto)}(function(d){function e(){}function m(e,t){y.ev.on(i+e+b,t)}function u(e,t,i,a){var r=document.createElement("div");return r.className="mfp-"+e,i&&(r.innerHTML=i),a?t&&t.appendChild(r):(r=d(r),t&&r.appendTo(t)),r}function p(e,t){y.ev.triggerHandler(i+e,t),y.st.callbacks&&(e=e.charAt(0).toLowerCase()+e.slice(1),y.st.callbacks[e]&&y.st.callbacks[e].apply(y,d.isArray(t)?t:[t]))}function f(e){return e===t&&y.currTemplate.closeBtn||(y.currTemplate.closeBtn=d(y.st.closeMarkup.replace("%title%",y.st.tClose)),t=e),y.currTemplate.closeBtn}function n(){d.magnificPopup.instance||((y=new e).init(),d.magnificPopup.instance=y)}var y,a,_,r,v,t,l="Close",c="BeforeClose",g="MarkupParse",h="Open",o="Change",i="mfp",b="."+i,j="mfp-ready",s="mfp-removing",w="mfp-prevent-close",Q=!!window.jQuery,C=d(window);e.prototype={constructor:e,init:function(){var e=navigator.appVersion;y.isIE7=-1!==e.indexOf("MSIE 7."),y.isIE8=-1!==e.indexOf("MSIE 8."),y.isLowIE=y.isIE7||y.isIE8,y.isAndroid=/android/gi.test(e),y.isIOS=/iphone|ipad|ipod/gi.test(e),y.supportsTransition=function(){var e=document.createElement("p").style,t=["ms","O","Moz","Webkit"];if(void 0!==e.transition)return!0;for(;t.length;)if(t.pop()+"Transition"in e)return!0;return!1}(),y.probablyMobile=y.isAndroid||y.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),_=d(document),y.popupsCache={}},open:function(e){var t;if(!1===e.isObj){y.items=e.items.toArray(),y.index=0;var i,a=e.items;for(t=0;t(e||C.height())},_setFocus:function(){(y.st.focus?y.content.find(y.st.focus).eq(0):y.wrap).focus()},_onFocusIn:function(e){if(e.target!==y.wrap[0]&&!d.contains(y.wrap[0],e.target))return y._setFocus(),!1},_parseMarkup:function(r,e,t){var n;t.data&&(e=d.extend(t.data,e)),p(g,[r,e,t]),d.each(e,function(e,t){if(void 0===t||!1===t)return!0;if(1<(n=e.split("_")).length){var i=r.find(b+"-"+n[0]);if(0'):i.attr(n[1],t)}}else r.find(b+"-"+e).html(t)})},_getScrollbarSize:function(){if(void 0===y.scrollbarSize){var e=document.createElement("div");e.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(e),y.scrollbarSize=e.offsetWidth-e.clientWidth,document.body.removeChild(e)}return y.scrollbarSize}},d.magnificPopup={instance:null,proto:e.prototype,modules:[],open:function(e,t){return n(),(e=e?d.extend(!0,{},e):{}).isObj=!0,e.index=t||0,this.instance.open(e)},close:function(){return d.magnificPopup.instance&&d.magnificPopup.instance.close()},registerModule:function(e,t){t.options&&(d.magnificPopup.defaults[e]=t.options),d.extend(this.proto,t.proto),this.modules.push(e)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'',tClose:"Close (Esc)",tLoading:"Loading..."}},d.fn.magnificPopup=function(e){n();var t=d(this);if("string"==typeof e)if("open"===e){var i,a=Q?t.data("magnificPopup"):t[0].magnificPopup,r=parseInt(arguments[1],10)||0;i=a.items?a.items[r]:(i=t,a.delegate&&(i=i.find(a.delegate)),i.eq(r)),y._openClick({mfpEl:i},t,a)}else y.isOpen&&y[e].apply(y,Array.prototype.slice.call(arguments,1));else e=d.extend(!0,{},e),Q?t.data("magnificPopup",e):t[0].magnificPopup=e,y.addGroup(t,e);return t};function k(){I&&(T.after(I.addClass(x)).detach(),I=null)}var x,T,I,M="inline";d.magnificPopup.registerModule(M,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){y.types.push(M),m(l+"."+M,function(){k()})},getInline:function(e,t){if(k(),e.src){var i=y.st.inline,a=d(e.src);if(a.length){var r=a[0].parentNode;r&&r.tagName&&(T||(x=i.hiddenClass,T=u(x),x="mfp-"+x),I=a.after(T).detach().removeClass(x)),y.updateStatus("ready")}else y.updateStatus("error",i.tNotFound),a=d("
");return e.inlineElement=a}return y.updateStatus("ready"),y._parseMarkup(t,{},e),t}}});function P(){E&&d(document.body).removeClass(E)}function S(){P(),y.req&&y.req.abort()}var E,O="ajax";d.magnificPopup.registerModule(O,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'The content could not be loaded.'},proto:{initAjax:function(){y.types.push(O),E=y.st.ajax.cursor,m(l+"."+O,S),m("BeforeChange."+O,S)},getAjax:function(r){E&&d(document.body).addClass(E),y.updateStatus("loading");var e=d.extend({url:r.src,success:function(e,t,i){var a={data:e,xhr:i};p("ParseAjax",a),y.appendContent(d(a.data),O),r.finished=!0,P(),y._setFocus(),setTimeout(function(){y.wrap.addClass(j)},16),y.updateStatus("ready"),p("AjaxContentAdded")},error:function(){P(),r.finished=r.loadError=!0,y.updateStatus("error",y.st.ajax.tError.replace("%url%",r.src))}},y.st.ajax.settings);return y.req=d.ajax(e),""}}});var z;d.magnificPopup.registerModule("image",{options:{markup:'
',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'The image could not be loaded.'},proto:{initImage:function(){var e=y.st.image,t=".image";y.types.push("image"),m(h+t,function(){"image"===y.currItem.type&&e.cursor&&d(document.body).addClass(e.cursor)}),m(l+t,function(){e.cursor&&d(document.body).removeClass(e.cursor),C.off("resize"+b)}),m("Resize"+t,y.resizeImage),y.isLowIE&&m("AfterChange",y.resizeImage)},resizeImage:function(){var e=y.currItem;if(e&&e.img&&y.st.image.verticalFit){var t=0;y.isLowIE&&(t=parseInt(e.img.css("padding-top"),10)+parseInt(e.img.css("padding-bottom"),10)),e.img.css("max-height",y.wH-t)}},_onImageHasSize:function(e){e.img&&(e.hasSize=!0,z&&clearInterval(z),e.isCheckingImgSize=!1,p("ImageHasSize",e),e.imgHidden&&(y.content&&y.content.removeClass("mfp-loading"),e.imgHidden=!1))},findImageSize:function(t){var i=0,a=t.img[0],r=function(e){z&&clearInterval(z),z=setInterval(function(){0
"),jQuery(document).on("dragover",function(e){e.preventDefault(),e.target!=this&&(jQuery("#rtm-media-gallery-uploader").show(),"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&i.addClass("rtm-drag-drop-active"),t.addClass("rtm-drag-drop-active"),jQuery("#rtm-drop-files-title").show())}).on("dragleave",function(e){if(e.preventDefault(),0!=e.originalEvent.pageX&&0!=e.originalEvent.pageY)return!1;"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&(i.removeClass("rtm-drag-drop-active"),i.removeAttr("style")),t.removeClass("rtm-drag-drop-active"),jQuery("#rtm-drop-files-title").hide()}).on("drop",function(e){e.preventDefault(),jQuery(".bp-suggestions").focus(),"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&(i.removeClass("rtm-drag-drop-active"),i.removeAttr("style")),t.removeClass("rtm-drag-drop-active"),jQuery("#rtm-drop-files-title").hide()}),jQuery(".rtmedia-container").on("click",".rtmedia-delete-album",function(e){e.preventDefault(),confirm(rtmedia_album_delete_confirmation)&&jQuery(this).closest("form").submit()}),jQuery(".rtmedia-container").on("click",".rtmedia-delete-media",function(e){e.preventDefault(),confirm(rtmedia_media_delete_confirmation)&&jQuery(this).closest("form").submit()}),rtmedia_init_action_dropdown(""),n(document).click(function(){n(".click-nav ul").is(":visible")&&n(".click-nav ul",this).hide()}),jQuery(".rtmedia-comment-link").on("click",function(e){e.preventDefault(),jQuery("#comment_content").focus()}),0m.showChars+m.minHideChars){var i=t.substr(0,m.showChars);if(0<=i.indexOf("<")){for(var a=!1,r="",n=0,o=[],s=null,l=0,c=0;c<=m.showChars;l++)if("<"!=t[l]||a||(a=!0,"/"==(s=t.substring(l+1,t.indexOf(">",l)))[0]?s!="/"+o[0]?m.errMsg="ERROR en HTML: the top of the stack should be the tag that closes":o.shift():"br"!=s.toLowerCase()&&o.unshift(s)),a&&">"==t[l]&&(a=!1),a)r+=t.charAt(l);else if(c++,n<=m.showChars)r+=t.charAt(l),n++;else if(0";break}i=u("").html(r+''+m.ellipsesText+"").html()}else i+=m.ellipsesText;var d='
'+i+'
'+t+'
'+m.moreText+"";e.html(d),e.find(".allcontent").hide(),u(".shortcontent p:last",e).css("margin-bottom",0)}}))}}(jQuery),window.onload=function(){"undefined"!=typeof rtmedia_masonry_layout&&"true"==rtmedia_masonry_layout&&0==jQuery(".rtmedia-container .rtmedia-list.rtm-no-masonry").length&&rtm_masonry_reload(rtm_masonry_container),rtm_search_media_text_validation(),check_condition("search")&&jQuery("#media_search_remove").show()},jQuery(document).ready(function(){rtm_upload_terms_activity(),jQuery("body").hasClass("has-sidebar")&&0===jQuery("#secondary").length&&(jQuery(".rtmedia-single-container").length||jQuery(".rtmedia-container").length)&&jQuery("body").removeClass("has-sidebar"),rtmedia_main&&("undefined"!==rtmedia_main.rtmedia_direct_download_link&&parseInt(rtmedia_main.rtmedia_direct_download_link)||jQuery(document).on("bp_ajax_request",function(e){setTimeout(function(){jQuery("video").each(function(){jQuery(this).attr("controlsList","nodownload"),jQuery(this).attr("playsinline","playsinline"),jQuery(this).load()})},200)}))});
\ No newline at end of file
+var rtMagnificPopup,rtm_masonry_container,comment_media=!1;function apply_rtMagnificPopup(e){jQuery("document").ready((function(t){var i="";if(i="undefined"==typeof rtmedia_load_more?"Loading media":rtmedia_load_more,"undefined"!=typeof rtmedia_lightbox_enabled&&"1"==rtmedia_lightbox_enabled){var a,r,n=!1;t(".activity-item .rtmedia-activity-container .rtmedia-list-item > a").siblings("p").children("a").length>0&&t(".activity-item .rtmedia-activity-container .rtmedia-list-item > a").siblings("p").children("a").addClass("no-popup"),rtMagnificPopup=jQuery(e).magnificPopup({delegate:"a:not(.no-popup, .mejs-time-slider, .mejs-volume-slider, .mejs-horizontal-volume-slider)",type:"ajax",fixedContentPos:!0,fixedBgPos:!0,tLoading:i+" #%curr%...",mainClass:"mfp-img-mobile",preload:[1,3],closeOnBgClick:!0,gallery:{enabled:!0,navigateByImgClick:!0,arrowMarkup:"",preload:[0,1]},image:{tError:'The image #%curr% could not be loaded.',titleSrc:function(e){return e.el.attr("title")+"by Marsel Van Oosten"}},callbacks:{ajaxContentAdded:function(){e=jQuery.magnificPopup.instance,1===jQuery(e.items).size()&&jQuery(".mfp-arrow").remove();var e=jQuery.magnificPopup.instance,i=e.currItem.el,o=i.parent();if(o.is("li")||(o=o.parent()),(o.is(":nth-last-child(2)")||o.is(":last-child"))&&o.find("a").hasClass("rtmedia-list-item-a")){o.next();"block"==jQuery("#rtMedia-galary-next").css("display")&&(n||(a=e.ev.children(),n=!0,r=nextpage),jQuery("#rtMedia-galary-next").click())}var m=e.items.length;if(e.index!=m-1||o.is(":last-child")){"undefined"!=typeof _wpmejsSettings&&_wpmejsSettings.pluginPath;var d=jQuery(".rtmedia-container .rtmedia-single-meta").height(),l=!1;void 0!==e&&void 0!==e.probablyMobile&&1==e.probablyMobile&&(l=!0),t(".mfp-content .rtmedia-single-media .wp-audio-shortcode,.mfp-content .rtmedia-single-media .wp-video-shortcode,.mfp-content .rtmedia-single-media .bp_media_content video").attr("autoplay",!0),l&&t(".mfp-content .rtmedia-single-media .wp-video-shortcode,.mfp-content .rtmedia-single-media .bp_media_content video").attr("muted",!1),t(".mfp-content .rtmedia-single-media .wp-audio-shortcode,.mfp-content .rtmedia-single-media .wp-video-shortcode,.mfp-content .rtmedia-single-media .bp_media_content video").mediaelementplayer({classPrefix:"mejs-",defaultVideoWidth:480,hideVolumeOnTouchDevices:!1,features:["playpause","progress","current","volume","fullscreen"],defaultVideoHeight:270,alwaysShowControls:l,enableAutosize:!0,clickToPlayPause:!0,videoHeight:-1,success:function(e,i){e.addEventListener("loadeddata",(function(i){var a=t(e).height(),r=t(window).height(),n=jQuery("div.rtm-ltb-action-container").height(),o=d-(n=n+50);a>r&&jQuery(".rtmedia-container #rtmedia-single-media-container .mejs-container").attr("style","height:"+o+"px !important; transition:0.2s")}),!1),l&&t(e).hasClass("wp-video-shortcode")?jQuery("body").on("touchstart",".mejs-overlay-button",(function(t){e.paused?e.play():e.pause()})):e.pause()}}),t(".mfp-content .mejs-audio .mejs-controls").css("position","relative"),rtMediaHook.call("rtmedia_js_popup_after_content_added",[]),"undefined"!=typeof bp&&void 0!==bp.mentions&&void 0!==bp.mentions.users&&(t("#atwho-container #atwho-ground-comment_content").remove(),t("#comment_content").bp_mentions(bp.mentions.users)),rtmedia_reset_video_and_audio_for_popup(),apply_rtMagnificPopup(".rtmedia-list-media.rtm-gallery-list, .rtmedia-activity-container ul.rtmedia-list, #bp-media-list,.bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content, .rtm-bbp-container, ul.rtm-comment-container")}else i.click()},open:function(){var e=jQuery(".mfp-bg"),t=jQuery(".mfp-wrap");e.height(e.height()+t.height())},close:function(e){n&&(mfp.ev.empty(),mfp.ev.append(a),nextpage=r,n=!1,nextpage>1&&jQuery("#rtMedia-galary-next").show()),rtmedia_single_page_popup_close()},BeforeChange:function(e){}}})}jQuery(document).ajaxComplete((function(){jQuery("[id^=imgedit-leaving]").filter((function(){var e=jQuery(this).text();jQuery(this).text(e.replace("OK","Save"))}))}))}))}jQuery(document).ready((function(){if("object"==typeof rtmedia_bp)for(var e in rtmedia_bp)window[e]=rtmedia_bp[e];if("object"==typeof rtmedia_main)for(var e in rtmedia_main)window[e]=rtmedia_main[e];if("object"==typeof rtmedia_upload_terms)for(var e in rtmedia_upload_terms)window[e]=rtmedia_upload_terms[e];if("object"==typeof rtmedia_magnific)for(var e in rtmedia_magnific)window[e]=rtmedia_magnific[e]}));var rtMediaHook={hooks:[],is_break:!1,register:function(e,t){void 0===rtMediaHook.hooks[e]&&(rtMediaHook.hooks[e]=[]),rtMediaHook.hooks[e].push(t)},call:function(e,arguments){if(void 0!==rtMediaHook.hooks[e])for(i=0;i span,"+e+" .click-nav > div").toggleClass("no-js js"),jQuery(e+" .click-nav .js ul").hide(),jQuery(e+" .click-nav .clicker").click((function(e){t=jQuery("#rtm-media-options .click-nav .clicker").next("ul"),i=jQuery(this).next("ul"),jQuery.each(t,(function(e,t){jQuery(t).html()!=i.html()&&jQuery(t).hide()})),jQuery(i).toggle(),e.stopPropagation()}))}function bp_media_create_element(e){return!1}function rtmedia_version_compare(e,t){if(typeof e+typeof t!="stringstring")return!1;for(var i=e.split("."),a=t.split("."),r=0,n=Math.max(i.length,a.length);r0||parseInt(i[r])>parseInt(a[r]))return!0;if(a[r]&&!i[r]&&parseInt(a[r])>0||parseInt(i[r])0}function rtm_masonry_reload(e){setTimeout((function(){e.masonry("reload")}),250)}function rtm_search_media_text_validation(){""===jQuery("#media_search_input").val()?jQuery("#media_search").css("cursor","not-allowed"):jQuery("#media_search").css("cursor","pointer")}function rtmediaGetParameterByName(e){e=e.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var t=new RegExp("[\\?&]"+e+"=([^]*)").exec(location.search);return null==t?"":decodeURIComponent(t[1].replace(/\+/g," "))}function rtmedia_single_media_alert_message(e,t,i){var a="rtmedia-success";"warning"==t&&(a="rtmedia-warning");var r=!1;jQuery(".rtmedia-message-container").each((function(e,t){return t=jQuery(t),i&&t.hasClass("rtmedia-empty-comment-error-class")?(t.remove(),r=!0,!1):void 0!==i||t.hasClass("rtmedia-empty-comment-error-class")?void 0:(t.remove(),r=!0,!1)}));var n,o=jQuery("
';
+ }
+ }
+ }
+
+ // Final video output appended to cleaned content
+ if ( $godam_videos ) {
+ $godam_videos = '
' . $godam_videos . '
';
+ }
+
+ return wp_kses_post( $clean_content ) . $godam_videos;
+ }, 10 );
+
+ /**
+ * Handle AJAX request for loading a single activity comment's HTML.
+ */
+ add_action( 'wp_ajax_get_single_activity_comment_html', 'handle_get_single_activity_comment_html' );
+ add_action( 'wp_ajax_nopriv_get_single_activity_comment_html', 'handle_get_single_activity_comment_html' );
+
+ function handle_get_single_activity_comment_html() {
+ check_ajax_referer( 'godam-ajax-nonce', 'nonce' );
+
+ $activity_id = isset( $_POST['comment_id'] ) ? intval( $_POST['comment_id'] ) : 0;
+
+ if ( ! $activity_id ) {
+ wp_send_json_error( 'Invalid activity ID' );
+ }
+
+ $activity = new BP_Activity_Activity( $activity_id );
+ if ( empty( $activity->id ) ) {
+ wp_send_json_error( 'Activity comment not found' );
+ }
+
+ global $activities_template;
+
+ // Backup original activity
+ $original_activity = $activities_template->activity ?? null;
+
+ // Replace global for template rendering
+ $activities_template = new stdClass();
+ $activities_template->activity = $activity;
+
+ ob_start();
+ bp_get_template_part( 'activity/entry' );
+ $html = ob_get_clean();
+
+ // Restore original
+ if ( $original_activity ) {
+ $activities_template->activity = $original_activity;
+ }
+
+ wp_send_json_success( [ 'html' => $html ] );
+ }
+
+}
+
+/**
+ * Enqueue the Magnific Popup script for rtMedia.
+ *
+ * This function ensures that the Magnific Popup script is loaded correctly on the frontend
+ * so that popup functionality works seamlessly with all combinations of plugin states:
+ * - When only rtMedia is active
+ * - When both rtMedia and Godam plugins are active
+ * - When Godam plugin is deactivated
+ *
+ * To achieve this, the script is deregistered first if already registered or enqueued,
+ * preventing conflicts or duplicates.
+ *
+ * When Godam plugin is active, the script is loaded without dependencies to avoid
+ * redundant or conflicting scripts. When Godam is not active, dependencies such as
+ * jQuery and rt-mediaelement-wp are included to ensure proper functionality.
+ *
+ * Enqueuing here guarantees consistent script loading regardless of Godam’s activation status.
+ */
+function enqueue_rtmedia_magnific_popup_script() {
+ $handle = 'rtmedia-magnific-popup';
+ $script_src = RTMEDIA_URL . 'app/assets/js/vendors/magnific-popup.js';
+ $version = RTMEDIA_VERSION;
+ $in_footer = true;
+
+ // Deregister the script if already registered or enqueued to prevent conflicts
+ if (wp_script_is($handle, 'registered') || wp_script_is($handle, 'enqueued')) {
+ wp_deregister_script($handle);
+ }
+
+ // Determine dependencies based on whether Godam integration is active
+ $dependencies = [];
+
+ // If Godam plugin is NOT active, add dependencies for jQuery and mediaelement
+ if (!defined('RTMEDIA_GODAM_ACTIVE') || !RTMEDIA_GODAM_ACTIVE) {
+ $dependencies = ['jquery', 'rt-mediaelement-wp'];
+ }
+
+ // Enqueue the Magnific Popup script with the appropriate dependencies
+ wp_enqueue_script($handle, $script_src, $dependencies, $version, $in_footer);
+}
+
+add_action('wp_enqueue_scripts', 'enqueue_rtmedia_magnific_popup_script');
diff --git a/index.php b/index.php
index 3d92d9395..558567272 100644
--- a/index.php
+++ b/index.php
@@ -3,7 +3,7 @@
* Plugin Name: rtMedia for WordPress, BuddyPress and bbPress
* Plugin URI: https://rtmedia.io/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
* Description: This plugin adds missing media rich features like photos, videos and audio uploading to BuddyPress which are essential if you are building social network, seriously!
- * Version: 4.6.23
+ * Version: 4.7.0
* Author: rtCamp
* Text Domain: buddypress-media
* Author URI: http://rtcamp.com/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
@@ -19,7 +19,7 @@
/**
* The version of the plugin
*/
- define( 'RTMEDIA_VERSION', '4.6.23' );
+ define( 'RTMEDIA_VERSION', '4.7.0' );
}
if ( ! defined( 'RTMEDIA_PATH' ) ) {
@@ -55,6 +55,22 @@
define( 'RTMEDIA_BASE_NAME', plugin_basename( __FILE__ ) );
}
+/**
+ * To prevent fatal errors when calling is_plugin_active(), we first check if the
+ * function exists. If it doesn't, we include the file manually to ensure the
+ * function is available.
+ */
+if ( ! function_exists( 'is_plugin_active' ) ) {
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
+}
+
+if ( ! defined( 'RTMEDIA_GODAM_ACTIVE' ) ) {
+ /**
+ * Check if Godam plugin is active and set constant accordingly.
+ */
+ define( 'RTMEDIA_GODAM_ACTIVE', is_plugin_active( 'godam/godam.php' ) );
+}
+
/**
* Auto Loader Function
*
diff --git a/readme.txt b/readme.txt
index 1b67646b4..b4ea9aeb8 100644
--- a/readme.txt
+++ b/readme.txt
@@ -4,8 +4,8 @@ Tags: BuddyPress, media, multimedia, album, audio, music, video, photo, upload,
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Requires at least: WordPress 4.1
-Tested up to: 6.8
-Stable tag: 4.6.23
+Tested up to: 6.8.1
+Stable tag: 4.7.0
Add albums, photo, audio/video upload, privacy, sharing, front-end uploads & more. All this works on mobile/tablets devices.
@@ -133,6 +133,18 @@ http://www.youtube.com/watch?v=dJrykKQGDcs
== Changelog ==
+= 4.7.0 [June 2, 2025] =
+
+* ENHANCEMENTS
+ * Added integration with GoDAM plugin's video player.
+ * Enabled support for GoDAM video player in rtMedia media gallery, BuddyPress activity stream, groups, and forums.
+ * Improved handling of player enqueue conditions based on GoDAM plugin status.
+ * Refined script loading to ensure compatibility across WordPress, BuddyPress, and rtMedia components.
+
+* FIXED
+ * Prevented conflicts with `mediaelement.js` when GoDAM plugin is active.
+ * Deregistered conflicting scripts to ensure seamless fallback and prevent duplication in player initialization.
+
= 4.6.23 [April 18, 2025] =
* Fixed
@@ -1922,6 +1934,9 @@ http://www.youtube.com/watch?v=dJrykKQGDcs
== Upgrade Notice ==
+= 4.7.0 =
+This update introduces comprehensive support for the GoDAM video player across rtMedia galleries and all BuddyPress components, including activity streams, groups, and forums.
+
= 4.6.23 =
rtMedia 4.6.23 with WP v6.8 compatibility, node package enhancements and updated admin notices.