diff --git a/admin/assets/js/get_snippets.js b/admin/assets/js/get_snippets.js
new file mode 100644
index 000000000..1ecb6f60a
--- /dev/null
+++ b/admin/assets/js/get_snippets.js
@@ -0,0 +1,535 @@
+// start the moment the document is ready
+var returnError = '
'+Joomla.JText._('COM_COMPONENTBUILDER_AN_ERROR_HAS_OCCURRED')+'! '+Joomla.JText._('COM_COMPONENTBUILDER_PLEASE_TRY_AGAIN_LATER')+'
';
+// add an ajax call tracker
+var ajaxcall = null;
+var fromLocal = false;
+
+jQuery(document).ready(function(){
+ getLibraries(snippetsPath);
+ jQuery('body').on('click','.getreaction',function(){
+ // Ajax request
+ var btn = jQuery(this);
+ btn.prop('disabled', true);
+ setTimeout(function(){
+ btn.prop('disabled', false);
+ }, 3000);
+ var type = btn.data('type');
+ if ('getLibraries' === type) {
+ getLibraries(snippetsPath);
+ } else if ('getSnippets' === type) {
+ var name = btn.data('name');
+ getSnippets(snippetsPath, name);
+ } else if ('all' === type) {
+ var status = btn.data('status');
+ bulkSnippetGithub(status);
+ } else if ('bulk' === type) {
+ checkBulkSnippetGithub();
+ } else if ('get' === type) {
+ var path = btn.data('path');
+ var status = btn.data('status');
+ setSnippetGithub(path, status);
+ } else {
+ var path = btn.data('path');
+ getSnippetModal(path, type);
+ }
+ });
+});
+
+// load every thing once ready
+jQuery(document).ajaxStop(function () {
+ if (0 === jQuery.active) {
+ //do something special
+ if ('snippets' === ajaxcall) {
+ setTimeout( function() {
+ jQuery('#snippets-github').html(''+Joomla.JText._('COM_COMPONENTBUILDER_JCB_COMMUNITY_SNIPPETS')+' ');
+ jQuery('#snippets-display').show();
+ jQuery('#snippets-grid').trigger('display.uk.check');
+ jQuery('#loading').hide();
+ }, 1000);
+ }
+ }
+});
+
+// get the libraries
+function getLibraries(path) {
+ var _paths = jQuery.jStorage.get('JCB-Snippets-Paths', null);
+ // always hide the snippets display
+ jQuery('#snippets-display').hide();
+ // always reset the grid
+ jQuery('#libraries-grid').html('');
+ // set the ajax scope
+ ajaxcall = 'libraries';
+ if (_paths) {
+ buildLibraries(_paths);
+ } else {
+ jQuery.get(path)
+ .success(function(paths) {
+ // load only this library paths
+ jQuery.jStorage.set('JCB-Snippets-Paths', paths, {TTL: expire});
+ buildLibraries(paths);
+ })
+ .error(function(jqXHR, textStatus, errorThrown) {
+ jQuery('#snippets-github').html(returnError);
+ });
+ }
+}
+
+// build the ibraries object
+function buildLibraries(paths) {
+ var _temp = jQuery.jStorage.get('JCB-Libraries', null);
+ if (_temp) {
+ setLibraries(_temp);
+ } else {
+ var temp = {};
+ jQuery.each(paths.tree, function(key,value) {
+ if (value.path.match(".json$")) {
+ var libName = value.path.split(/ -(.+)/)[0];
+ libName = libName.trim()
+ temp[libName] = libName;
+ }
+ });
+ // load only this library paths
+ jQuery.jStorage.set('JCB-Libraries', temp, {TTL: expire});
+ setLibraries(temp);
+ }
+}
+
+// set the libraries
+function setLibraries(names) {
+ // now load the lib buttons
+ jQuery.each(names, function(value) {
+ setLibrary(value);
+ });
+ setTimeout( function() {
+ jQuery('#snippets-github').html(''+Joomla.JText._('COM_COMPONENTBUILDER_AVAILABLE_LIBRARIES')+' ');
+ jQuery('#libraries-display').show();
+ jQuery('#libraries-grid').trigger('display.uk.check');
+ }, 1000);
+}
+
+// set the snippets
+function setLibrary(name) {
+ // get useful ID
+ var keyID = getKeyID(name);
+ // build the library display
+ var html = '';
+ html += '
';
+ html += '
' + name + ' ';
+ html += ' ';
+ // set the data buttons
+ html += setLibButtons(name);
+ // close the box panel
+ html += '';
+ html += '
';
+ // now we have the library
+ jQuery('#libraries-grid').append(html);
+}
+
+function setLibButtons(name) {
+ return ' '+Joomla.JText._('COM_COMPONENTBUILDER_OPEN_LIBRARY_SNIPPETS')+' ';
+}
+
+// get the snippets
+function getSnippets(path, libraryName) {
+ jQuery('#loading').show();
+ // get local values if set
+ var _paths = jQuery.jStorage.get('JCB-Snippets-Paths', null);
+ // always reset the grid
+ jQuery('#snippets-grid').html('');
+ // always hide libraries
+ jQuery('#libraries-display').hide();
+ // set the ajax scope
+ ajaxcall = 'snippets';
+ fromLocal = false;
+ if (_paths) {
+ setSnippets(_paths, libraryName);
+ jQuery('#snippets-github').html(''+Joomla.JText._('COM_COMPONENTBUILDER_JCB_COMMUNITY_SNIPPETS')+' ');
+ } else {
+ jQuery.get(path)
+ .success(function(paths) {
+ // load only this library paths
+ jQuery.jStorage.set('JCB-Snippets-Paths', paths, {TTL: expire});
+ setSnippets(paths, libraryName);
+ })
+ .error(function(jqXHR, textStatus, errorThrown) {
+ jQuery('#snippets-github').html(returnError);
+ });
+ }
+ // only use if loading localy
+ if (fromLocal) {
+ jQuery('#snippets-display').show();
+ jQuery('#snippets-grid').trigger('display.uk.check');
+ jQuery('#loading').hide();
+ }
+}
+
+// set the snippets
+function setSnippets(paths, libraryName) {
+ // set the ajax scope
+ ajaxcall = 'snippets';
+ jQuery.each(paths.tree, function(key,value) {
+ if (value.path.match(".json$") && value.path.match("^"+libraryName)) {
+ var _snippet = jQuery.jStorage.get(value.path, null);
+ if (_snippet) {
+ setSnippet(_snippet, value.path);
+ fromLocal = true;
+ } else {
+ jQuery.get(snippetPath+value.path)
+ .success(function(snippet) {
+ // convert the string to json.object
+ snippet = jQuery.parseJSON(snippet);
+ jQuery.jStorage.set(value.path, snippet, {TTL: expire});
+ setSnippet(snippet, value.path);
+ })
+ .error(function(jqXHR, textStatus, errorThrown) {
+ // we could do more
+ });
+ }
+ }
+ });
+}
+
+// set the snippets
+function setSnippet(snippet, key) {
+ // get useful ID
+ var keyID = getKeyID(key);
+ // get the status
+ var status = getSnippetStatus(snippet, key);
+ // add to bulk updater
+ if ('equal' !== status) {
+ bulkItems[status].push(key);
+ }
+ // build the snippet display
+ var html = '';
+ html += '
';
+ html += '
';
+ html += '
' + snippet.library+ ' - (' + snippet.type + ') ' + snippet.name + ' ';
+ html += snippet.heading + '
';
+ // set the data buttons
+ html += setDataButtons(snippet, key, status);
+ // set the snippet ref button
+ html += setRefButtons(snippet, key, status, keyID);
+ // set the contributor buttons
+ html += setContributorButtons(snippet, key);
+ // close the box panel
+ html += '
';
+ html += '
';
+ // now we have the snippet
+ jQuery('#snippets-grid').append(html);
+}
+
+// set the snippet status
+function getSnippetStatus(snippet, key) {
+ // check if JCB already has this snippet
+ if(local_snippets.hasOwnProperty(key)){
+ // first get local time stamp
+ var local_created = strtotime(local_snippets[key].created);
+ var local_modified = strtotime(local_snippets[key].modified);
+ // now get github time stamps
+ var created = strtotime(snippet.created);
+ var modified = strtotime(snippet.modified);
+ // work out the status
+ if (local_created == created) {
+ if (local_modified == modified) {
+ return 'equal';
+ } else if (local_modified > modified) {
+ return 'ahead';
+ } else if (local_modified < modified) {
+ return 'behind';
+ }
+ }
+ return 'diverged';
+ }
+ return 'new';
+}
+
+function setDataButtons(snippet, key, status) {
+ var html = '';
+ html += ' '+Joomla.JText._('COM_COMPONENTBUILDER_USAGE')+' ';
+ html += ' '+Joomla.JText._('COM_COMPONENTBUILDER_DESCRIPTION')+' ';
+ html += ' '+Joomla.JText._('COM_COMPONENTBUILDER_SNIPPET')+' ';
+ html += '
';
+ // return data buttons
+ return html;
+}
+
+function setRefButtons(snippet, key, status, keyID) {
+ var html = '';
+ // set the update button
+ html += '';
+ if ('equal' !== status) {
+ if ('new' === status) {
+ var tooltip = Joomla.JText._('COM_COMPONENTBUILDER_GET_THE_SNIPPET_FROM_GITHUB_AND_INSTALL_IT_LOCALLY');
+ } else {
+ var tooltip = Joomla.JText._('COM_COMPONENTBUILDER_GET_THE_SNIPPET_FROM_GITHUB_AND_UPDATE_THE_LOCAL_VERSION');
+ }
+ html += ' '+Joomla.JText._('COM_COMPONENTBUILDER_GET_SNIPPET')+' ';
+ } else {
+ html += ' '+Joomla.JText._('COM_COMPONENTBUILDER_LOCAL_SNIPPET')+' ';
+ }
+ html += '
';
+ // return data buttons
+ return html;
+}
+
+function setContributorButtons(snippet, key) {
+ // set the contributor name
+ if (snippet.contributor_company) {
+ var contributor_name = snippet.contributor_company;
+ } else if (snippet.contributor_name) {
+ var contributor_name = snippet.contributor_name;
+ } else {
+ var contributor_name = Joomla.JText._('COM_COMPONENTBUILDER_JCB_COMMUNITY');
+ }
+ // set the contributor url
+ if (snippet.contributor_website) {
+ var contributor_url = snippet.contributor_website;
+ } else if (snippet.contributor_email) {
+ var contributor_url = 'mailto:'+snippet.contributor_email;
+ } else {
+ var contributor_url = 'https://github.com/vdm-io/Joomla-Component-Builder-Snippets';
+ }
+ var html = '';
+ // return contributor buttons
+ return html;
+}
+
+// do a bulk update
+function checkBulkSnippetGithub() {
+ // check if there is new items
+ if (bulkItems.new.length === 0) {
+ jQuery('#bulk-button-new').prop('disabled', true);
+ jQuery('#bulk-button-new').attr('title', Joomla.JText._('COM_COMPONENTBUILDER_THERE_ARE_NO_NEW_SNIPPETS_AT_THIS_TIME'));
+ jQuery('#bulk-notice-new').show();
+ }
+ // check if there is diverged items
+ if (bulkItems.diverged.length === 0) {
+ jQuery('#bulk-button-diverged').prop('disabled', true);
+ jQuery('#bulk-button-diverged').attr('title', Joomla.JText._('COM_COMPONENTBUILDER_THERE_ARE_NO_DIVERGED_SNIPPETS_AT_THIS_TIME'));
+ jQuery('#bulk-notice-diverged').show();
+ }
+ // check if there is ahead items
+ if (bulkItems.ahead.length === 0) {
+ jQuery('#bulk-button-ahead').prop('disabled', true);
+ jQuery('#bulk-button-ahead').attr('title', Joomla.JText._('COM_COMPONENTBUILDER_THERE_ARE_NO_AHEAD_SNIPPETS_AT_THIS_TIME'));
+ jQuery('#bulk-notice-ahead').show();
+ }
+ // check if there is behind items
+ if (bulkItems.behind.length === 0) {
+ jQuery('#bulk-button-behind').prop('disabled', true);
+ jQuery('#bulk-button-behind').attr('title', Joomla.JText._('COM_COMPONENTBUILDER_THERE_ARE_NO_OUT_OF_DATE_SNIPPETS_AT_THIS_TIME'));
+ jQuery('#bulk-notice-behind').show();
+ }
+ // check if all we should close the all button
+ if (bulkItems.behind.length === 0 && bulkItems.new.length === 0 && bulkItems.ahead.length === 0 && bulkItems.diverged.length === 0) {
+ jQuery('#bulk-button-all').prop('disabled', true);
+ jQuery('#bulk-button-all').attr('title', Joomla.JText._('COM_COMPONENTBUILDER_THERE_ARE_NO_SNIPPETS_TO_UPDATE_AT_THIS_TIME'));
+ jQuery('#bulk-notice-all').show();
+ }
+}
+
+// do a bulk update
+function bulkSnippetGithub(status) {
+ // if all then trigger those with values
+ if ('all' === status) {
+ bulkSnippetGithub('behind');
+ bulkSnippetGithub('new');
+ bulkSnippetGithub('ahead');
+ bulkSnippetGithub('diverged');
+ } else if (bulkItems[status].length > 0) {
+ jQuery.each(bulkItems[status], function(i, key){
+ setTimeout(function(){
+ doBulkUpdate_server(key, status).done(function(result) {
+ if (result.message) {
+ // only show errors
+ if ('error' === result.status || 'warning' === result.status) {
+ UIkit.notify(result.message, {status: result.status});
+ }
+ // update local items
+ if ('success' === result.status) {
+ // get key ID
+ var keyID = getKeyID(key);
+ // update snippet if we can
+ updateSnippetDisplay(keyID, 'equal');
+ }
+ } else {
+ UIkit.notify(Joomla.JText._('COM_COMPONENTBUILDER_SNIPPET_COULD_NOT_BE_UPDATEDSAVED'), {status:'danger'});
+ }
+ });
+ }, 200);
+ });
+ // reset array
+ bulkItems[status].length = 0;
+ // update the buttons (since we only do the bulk update once)
+ checkBulkSnippetGithub();
+ }
+}
+
+function doBulkUpdate_server(path, status) {
+ // set the ajax scope
+ ajaxcall = null;
+ var getUrl = "index.php?option=com_componentbuilder&task=ajax.setSnippetGithub&format=json";
+ if (token.length > 0 && path.length > 0 && status.length > 0) {
+ var request = 'token='+token+'&path='+path+'&status='+status;
+ }
+ return jQuery.ajax({
+ type: 'POST',
+ url: getUrl,
+ dataType: 'jsonp',
+ data: request,
+ jsonp: 'callback'
+ });
+}
+
+// set the snippet from gitHub
+function setSnippetGithub(key, status) {
+ var message = getConfirmUpdate(status);
+ UIkit.modal.confirm(message, function(){
+ // will be executed on confirm.
+ setSnippetGithub_server(key, status).done(function(result) {
+ if (result.message) {
+ UIkit.notify(result.message, {status: result.status});
+ if ('success' === result.status) {
+ // get key ID
+ var keyID = getKeyID(key);
+ // update snippet if we can
+ updateSnippetDisplay(keyID, 'equal');
+ }
+ } else {
+ UIkit.notify(Joomla.JText._('COM_COMPONENTBUILDER_SNIPPET_COULD_NOT_BE_UPDATEDSAVED'), {status:'danger'});
+ }
+ });
+ });
+}
+
+function setSnippetGithub_server(path, status) {
+ // set the ajax scope
+ ajaxcall = null;
+ var getUrl = "index.php?option=com_componentbuilder&task=ajax.setSnippetGithub&format=json";
+ if (token.length > 0 && path.length > 0 && status.length > 0) {
+ var request = 'token='+token+'&path='+path+'&status='+status;
+ }
+ return jQuery.ajax({
+ type: 'POST',
+ url: getUrl,
+ dataType: 'jsonp',
+ data: request,
+ jsonp: 'callback'
+ });
+}
+
+// update the snippet display
+function updateSnippetDisplay(keyID, status) {
+ // update badge
+ jQuery('#'+keyID+'-badge').html(' ' +status);
+ jQuery('#'+keyID+'-badge').attr('href' , '#'+status+'-meaning');
+ // update button
+ if ('equal' === status) {
+ // update notice
+ jQuery('#'+keyID+'-getbutton').attr('title', Joomla.JText._('COM_COMPONENTBUILDER_NO_NEED_TO_GET_IT_SINCE_IT_IS_ALREADY_IN_SYNC_WITH_YOUR_LOCAL_VERSION'));
+ jQuery('#'+keyID+'-getbutton').prop('disabled', true);
+ jQuery('#'+keyID+'-getbutton').html(' ' + Joomla.JText._('COM_COMPONENTBUILDER_LOCAL_SNIPPET'));
+ // counter delay just incase
+ setTimeout(function(){
+ jQuery('#'+keyID+'-getbutton').prop('disabled', true);
+ }, 2000);
+ }
+ // update the data filter
+ jQuery('#'+keyID+'-panel').attr('data-uk-filter', status);
+ // tell the grid to update
+ jQuery('#snippets-grid').trigger('display.uk.check');
+}
+
+// set the modal
+function getSnippetModal(key, type) {
+ // set the ajax scope
+ ajaxcall = 'snippets';
+ var _snippet = jQuery.jStorage.get(key, null);
+ if (_snippet) {
+ // show modal
+ showSnippetModal(_snippet, type);
+ } else {
+ jQuery.get('https://raw.githubusercontent.com/vdm-io/Joomla-Component-Builder-Snippets/master/'+key)
+ .success(function(snippet) {
+ // convert the string to json.object
+ snippet = jQuery.parseJSON(snippet);
+ jQuery.jStorage.set(key, snippet, {TTL: expire});
+ // show modal
+ showSnippetModal(snippet, type);
+ })
+ .error(function(jqXHR, textStatus, errorThrown) {
+ // we could do more
+ });
+ }
+}
+
+// show the modal
+function showSnippetModal(snippet, type) {
+ var html = '';
+ html += '
';
+ html += '
' + snippet.library + ' - (' + snippet.type + ') ' + snippet.name + ' ';
+ if ('contributor' === type) {
+ html += '
';
+ html += ' '+Joomla.JText._('COM_COMPONENTBUILDER_COMPANY_NAME')+' ';
+ html += ''+snippet.contributor_company+' ';
+ html += ' '+Joomla.JText._('COM_COMPONENTBUILDER_AUTHOR_NAME')+' ';
+ html += ''+snippet.contributor_name+' ';
+ html += ' '+Joomla.JText._('COM_COMPONENTBUILDER_AUTHOR_EMAIL')+' ';
+ html += ''+snippet.contributor_email+' ';
+ html += ' '+Joomla.JText._('COM_COMPONENTBUILDER_AUTHOR_WEBSITE')+' ';
+ html += ''+snippet.contributor_website+' ';
+ html += ' ';
+ } else {
+ html += '
';
+ }
+ html += '
C: ' + snippet.created + ' | M: ' + snippet.modified + ' ';
+ html += '
';
+ // get current page position
+ var scroll = jQuery(window).scrollTop();
+ // add html to modal
+ var modal = UIkit.modal.blockUI(html, {center:true, bgclose:true}).on({
+ 'hide.uk.modal': function(){
+ // scroll fix since the modal pops to the top of the page
+ jQuery(window).scrollTop(scroll);
+ }
+ });
+ // show modal
+ modal.show();
+}
+
+// get key ID
+function getKeyID(key) {
+ // get useful ID
+ var keyID = key.replace('-', '');
+ keyID = keyID.replace('.json', '');
+ keyID = keyID.replace(/\s+/ig, '-');
+ keyID = keyID.replace(/\(/g, '');
+ keyID = keyID.replace(/\)/g, '');
+ // return the id build
+ return keyID;
+}
+
+// set the snippet from gitHub
+function getConfirmUpdate(status) {
+ switch(status) {
+ case 'new':
+ return Joomla.JText._('COM_COMPONENTBUILDER_ARE_YOU_SURE_YOU_WOULD_LIKE_TO_ADD_THIS_NEW_JCB_COMMUNITY_SNIPPET_TO_YOUR_LOCAL_SNIPPETS');
+ break;
+ case 'behind':
+ return Joomla.JText._('COM_COMPONENTBUILDER_ARE_YOU_SURE_YOU_WOULD_LIKE_TO_UPDATE_YOUR_LOCAL_SNIPPET_WITH_THIS_NEWER_JCB_COMMUNITY_SNIPPET');
+ break;
+ case 'ahead':
+ return Joomla.JText._('COM_COMPONENTBUILDER_ARE_YOU_SURE_YOU_WOULD_LIKE_TO_UPDATE_YOUR_LOCAL_SNIPPET_WITH_THIS_OLDER_JCB_COMMUNITY_SNIPPET');
+ break;
+ case 'diverged':
+ return Joomla.JText._('COM_COMPONENTBUILDER_ARE_YOU_SURE_YOU_WOULD_LIKE_TO_REPLACE_YOUR_LOCAL_SNIPPET_WITH_THIS_JCB_COMMUNITY_SNIPPET');
+ break;
+ default:
+ return Joomla.JText._('COM_COMPONENTBUILDER_ARE_YOU_SURE_YOU_WOULD_LIKE_TO_CONTINUE');
+ break;
+ }
+}