UNPKG

bootstrap-help-manager

Version:

Plugin and management console to create and manage help icons and content across an entire site.

602 lines (539 loc) 21.1 kB
/** * Bootstrap-Help-Manager v 0.5.2 * https://github.com/psalmody/Bootstrap-Help-Manager */ /** * JSONTable plugin - takes jsondata or url and converts to bootstrap table */ (function ($) { $.fn.JSONTable = function (options) { var settings = $.extend({}, { url: false, data: false, method: 'GET', tableClasses: 'table-condensed table-striped', responsive: false, dataType: 'JSON', appendTo: false, noWraps: [], success: false, nodata: false, columns: [], options: {}, template: false, ajaxstatus: false, templateParams: {} }, options) if (!settings.url && !settings.data) { console.log('url or data must be specified for JSONTable plugin.'); return; } var table, thead, tbody, div; var self = this; if (settings.data) { formatData(settings.data, 'local, no ajax', false); } else { $.ajax({ method: settings.method, url: settings.url, data: settings.options, dataType: settings.dataType }).done(function ( data, status, xhr ) { formatData( data, status, xhr ); }).fail(function ( xhr, status, error) { if (typeof(settings.fail) == 'function') { settings.fail(xhr, status, error); } }); } function formatData( data, status, xhr ) { if (data.length < 1) { if (typeof (settings.nodata) == 'function') { settings.nodata(table, status, xhr); } return self; } if (self.prop('tagName') != 'TABLE') { div = self; div.empty(); table = $('<table class="table ' + settings.tableClasses + '"><thead></thead><tbody></tbody></table>'); div.append(table); if (settings.responsive) { div.addClass('table-responsive'); } table.hide(); } else { table = self; div = self.closest('div'); if (settings.tableClasses) { table.addClass(settings.tableClasses); } if (settings.responsive) { div.addClass('table-responsive'); } } if (table.find('thead').length > 0) { thead = table.find('thead'); } else { thead = $('<thead></thead>'); table.append(thead); } if (table.find('tbody').length > 0) { tbody = table.find('tbody'); tbody.empty(); } else { tbody = $('<tbody></tbody>'); table.append(tbody); } if (thead.find('tr').length < 1) { var tr = $('<tr></tr>'); thead.append(tr); if (settings.columns.length > 0) { $.each(settings.columns, function (i) { var th = $('<th></th>'); tr.append(th); th.html(settings.columns[i]); }) } else { $.each(data[0], function (k, v) { var th = $('<th></th>'); tr.append(th); th.html(k); }); } } $(data).each(function () { if (settings.template) { tbody.append(BHM.tmpl(settings.template.html(),$.extend(this,settings.templateParams))); return; } var tr = $('<tr></tr>'); tbody.append(tr); $.each(this, function (k, v) { var td = $('<td></td>'); if (settings.noWraps.indexOf(k) >= 0 || settings.noWraps.indexOf('allrows') >= 0) { td.addClass('noWrap'); } tr.append(td); td.html(v); }) }); table.show(); if (typeof (settings.success) == 'function') { settings.success(table, status, xhr ); } return self; } } }(jQuery)); ; // Simple JavaScript Templating // John Resig - http://ejohn.org/ - MIT Licensed var BHM = (function(my){ var cache = {}; my.tmpl = function tmpl(str, data){ // Figure out if we're getting a template, or if we need to // load the template - and be sure to cache the result. var fn = !/\W/.test(str) ? cache[str] = cache[str] || tmpl(document.getElementById(str).innerHTML) : // Generate a reusable function that will serve as a template // generator (and which will be cached). new Function("obj", "var p=[],print=function(){p.push.apply(p,arguments);};" + // Introduce the data as local variables using with(){} "with(obj){p.push('" + // Convert the template into pure JavaScript str .replace(/[\r\t\n]/g, " ") .split("<%").join("\t") .replace(/((^|%>)[^\t]*)'/g, "$1\r") .replace(/\t=(.*?)%>/g, "',$1,'") .split("\t").join("');") .split("%>").join("p.push('") .split("\r").join("\\'") + "');}return p.join('');"); // Provide some basic currying to the user return data ? fn( data ) : fn; }; return my; })(BHM || {}); ; /** * bhm.vertebrate.js - define Vertebrate models & collections */ var BHM = (function(Vertebrate, $, my) { my.helper = Vertebrate.Model.Extend({ attributes: { id: -1, field_selecter: '', title: '', large: false, html: '', page_ids: '' }, /*url: BHM.helpersurl*/ }) my.page = Vertebrate.Model.Extend({ attributes: { "id": -1, "url": '' }, /*url: BHM.pagesurl*/ }); my.helpers = Vertebrate.Collection.Extend({ model: my.helper, /*url: BHM.helpersurl*/ }); my.pages = Vertebrate.Collection.Extend({ model: my.page, /*url: BHM.pagesurl*/ }); my.cp = new my.pages(); my.ch = new my.helpers(); return my; }(Vertebrate, jQuery, BHM || {})); ; /* * bhm.console.render.js render functions for BHM */ var BHM = (function(Vertebrate, $, my) { //clean the url for use as DOM id var clean = function(what) { if (typeof(what) != 'string') return what; return what.replace(/([.])|([/])|([ ])/g, ''); } //render a single page var renderPage = function( model ) { var $el = BHM.mc.$el; cleanfilename = clean(model.get('url')); //add a panel $el.find('.panel-group').append(BHM.tmpl($('#templatePanel').html(),$.extend({},{clean:cleanfilename},model.attributes))); //first panel gets open $el.find('.panel-collapse:first').addClass('in'); } //render helps by page var renderHelps = function( model ) { var $el = BHM.mc.$el; //we'll be attaching to this panel content var panel = $('#bhmpanel'+model.get('id')+' .panel-body'); //columns for JSONTable from mc settings var cols = BHM.mc.settings.columns.slice(0); cols.push(BHM.mc.settings.addButton); //get all helps that are on this page var jsondata = []; var helps = []; var pageid = model.get('id'); $.each(BHM.ch.models,function(k,v) { if (this.get('page_ids').indexOf(pageid) > -1) helps.push(this); }); $.each(helps,function() { jsondata.push(this.attributes); }); //create JSONTable from group of helps panel.JSONTable({ data: jsondata, template: $('#templateHelperRow'), columns: cols, success: function() { $('.helpHTML').hide(); } }); } //render only one help var renderHelp = function( model ) { var $el = BHM.mc.$el; //if there isn't a table yet, create one by running this as renderHelps if (!$('#bhmpanel'+model.get('page_ids')+' .panel-body tbody').length) { var page = BHM.cp.find(model.get('page_ids'),'id'); renderHelps( page ); return true; } //get filename, find tbody and prepend a new row var page_ids = model.get('page_ids').split(','); $.each(page_ids,function(k,v) { var prependto = false; $('#bhmpanel'+v+' .panel-body tbody tr').each(function() { var help = BHM.ch.find($(this).data('help-id'),'id'); if (model.get('field_selecter') > help.get('field_selecter')) { return true; } else { prependto = $(this); return false; } }); var newrow = BHM.tmpl($('#templateHelperRow').html(),model.get()); if (!prependto) { $('#bhmpanel'+v+' .panel-body tbody').append(newrow); } else { prependto.before(newrow); } }); if (page_ids.length > 1) $('.help'+model.get('id')).addClass('info'); } //cp - pages collections - render my.cp = BHM.cp || {}; my.cp.render = function() { var self = this; var models = this.models; var $el = BHM.mc.$el; $el.find('ul').empty(); $.each(models,function() { //render each page renderPage( this ); }); //add text and "Add New Page" button from template $el.prepend($('#templateOpeningText').html()); } //ch - helps collection - render all my.ch = BHM.ch || {}; my.ch.render = function() { var self = this; var pages = BHM.cp.models; var $el = BHM.mc.$el; $.each(pages,function() { //render helps for each page renderHelps( this ); }) } //publicize these functions my.renderHelp = function(model) { return renderHelp(model); }; my.renderPage = function( model ) { return renderPage(model); }; my.clean = function( filename ) { return clean(filename); } //keep track of console and settings in BHM.mc my.mc = { settings: { addButton: '<button class="btn btn-sm btn-default btn-block addHelper">Add</button>', columns: ['Field Selecter', 'Modal Title', 'Size', 'Content', 'Save'], ajaxFail: false, templateurl: "", helpersurl: "", pagesurl: "" }, $el: '', // jQuery object which the console isn't put in render: function() { //render this object - setup a few important things var self = this; BHM.ch.url = this.settings.helpersurl; BHM.cp.url = this.settings.pagesurl; BHM.helper.prototype.url = this.settings.helpersurl; BHM.page.prototype.url = this.settings.pagesurl; //get templates and setup CKEDITOR in modal var dfd = $.get(self.settings.templateurl); //setup tabpanel, CKEDITOR in modal when templates are loaded, then fetch collections $.when(dfd) .then(function( data ) { $('body').append(data); CKEDITOR.replace('bhmTextareaEditor'); self.$el.append(BHM.tmpl($('#templatePanelGroup').html(), {})); }) .then(function() { return BHM.cp.fetch() }) .then(function() { return BHM.ch.fetch() }); } } return my; }(Vertebrate, jQuery, BHM || {})); ; /* bhm.console.js */ //setup ckeditor styles (function(CKEDITOR, $) { //css for CKEDITOR is every stylesheet on this page var cssfiles = $(document).find('link[rel="stylesheet"]'); var arrcss = ['body{padding:5px;}']; cssfiles.each(function() { arrcss.push($(this).attr('href')); }); CKEDITOR.config.contentsCss = arrcss; CKEDITOR.config.height = 500; CKEDITOR.config.htmlEncodeOutput = false; CKEDITOR.config.entities = false; }(CKEDITOR, jQuery)); (function($) { $.fn.BHMConsole = function(opts) { var mc = BHM.mc; mc.settings = $.extend({},mc.settings,opts); mc.$el = this; mc.render(); var self = this; var getPageFor = function( $obj ) { return BHM.cp.find($obj.closest('.panel-default').data('pageid'),'id'); }; var getHelpFor = function( $obj ) { return BHM.ch.find($obj.closest('tr').data('help-id'),'id'); }; var getElForHelp = function( model ) { return $('.help'+model.get('id')); }; $(document).on('vertebrate:fetched', function(e, c, ms) { c.render(); }).on('vertebrate:changeattr',function(e,m,mattr,mchanged) { if (m.has('url')) return false; getElForHelp(m).find('.saveHelp').addClass('btn-warning'); }); $(this).on('change','input[type="text"]',function() { var model = getHelpFor($(this)), attr = $(this).data('attr'), val = $(this).val(); if (val == model.get(attr)) return false; model.set($(this).data('attr'),$(this).val()); }).on('click','input[type="checkbox"]',function() { var val = $(this).is(':checked') ? 1 : 0, model = getHelpFor($(this)), old = model.get($(this).data('attr')); if (val == old) return false; model.set($(this).data('attr'),val); }).on('click','.saveHelp',function() { var help = getHelpFor( $(this) ); help.save(); var el = getElForHelp(help); el.find('.saveHelp').removeClass('btn-warning'); }).on('click','.deleteHelp',function() { var sure = confirm('Are you sure you want to delete this row?'); if (!sure) return false; var model = getHelpFor($(this)); var page = getPageFor($(this)); var modelel = getElForHelp(model); var panel = modelel.closest('.panel'); BHM.ch.remove(model); $.when(model.delete()).done(function() { var help_pages = model.get('page_ids').split(','); modelel.fadeOut(300,function() { modelel.remove(); $.each(help_pages,function() { if (!panel.find('tbody tr').length) { page.delete(); panel.fadeOut(300,function() { $(this).remove(); self.find('.panel-title').children('a').click(); }) } }) }); }); }).on('click','.addHelper',function() { var page = getPageFor($(this)); var model = new BHM.helper({ id: BHM.ch.next('id').toString(), "page_ids": page.get('id') }); BHM.ch.add(model); BHM.renderHelp( model ); getElForHelp( model ).find('.saveHelp').addClass('btn-warning'); }).on('click','.editHelp',function() { var model = getHelpFor($(this)); var modal = $('#bhmEditHtmlModal'); $('#bhmEditHtmlModalFieldselecter').text(model.get('field_selecter')); CKEDITOR.instances['bhmTextareaEditor'].setData(model.get('html')); modal.data('helpId',model.get('id')); modal.modal(); }).on('click','#BHMaddPage',function() { var url = prompt('Enter the relative url of the page to add to:'); if (url.length < 1) return false; var id = BHM.cp.next('id').toString();; var page = new BHM.page({ "id": id, "url": url }); var help = new BHM.helper({ "id": BHM.ch.next('id'), "page_ids": id }) BHM.cp.add(page); BHM.ch.add(help); BHM.renderPage(page); BHM.renderHelp(help); page.save(); help.save(); $('#bhmpanelheader'+page.get('id')+' a:first').click(); }).on('click','.bhm-change-url',function() { page = getPageFor($(this)); var newurl = prompt("Enter the new url:",page.get('url')); if (!newurl) return false; page.set('url',newurl); page.save(); $(this).closest('.panel-title').children('a').text(newurl); }).on('click','.addToPages',function() { help = getHelpFor($(this)); var modal = $('#bhmSelectMultipleModal'); modal.data('helpid',help.get('id')); var pages = BHM.cp.models; var rows = []; $.each(pages,function() { var checkbox = '<input type="checkbox" value="'+this.get('id')+'">'; var row = { "checkbox": checkbox, url: this.get('url') }; rows.push(row); }); modal.find('.modal-body').JSONTable({ data: rows, columns: ['Appears On:','Page:'] }) modal.find('.modal-body tbody input[type="checkbox"]').each(function() { if (help.get('page_ids').indexOf($(this).val()) > -1) $(this).attr('checked',true); }) modal.modal(); }); //setup modal dialog $('body').on('click','#bhmEditHtmlModal .btn-save-html', function() { var modal = $('#bhmEditHtmlModal'), model = BHM.ch.find(modal.data('helpId'),'id'); model.set('html',CKEDITOR.instances['bhmTextareaEditor'].getData()); CKEDITOR.instances['bhmTextareaEditor'].setData(''); $('#bhmEditHtmlModal').modal('hide'); }); //setup multi-page dialog $('body').on('click','#bhmSelectMultipleModal .btn-save-page-ids',function() { var modal = $('#bhmSelectMultipleModal'), model = BHM.ch.find(modal.data('helpid'),'id'); //setup modal with all pages in it as checkboxes var newpageids = []; if (!modal.find('input[type="checkbox"]:checked').length) { alert('At least one checkbox must be selected.'); return false; } //for each checkbox :checked, make list of ids modal.find('input[type="checkbox"]:checked').each(function() { newpageids.push($(this).val()); }) var el = getElForHelp(model); if (newpageids.length > 1) { //we show the info class on helps that have multiple pages el.addClass('info'); } else { el.removeClass('info'); } newpageids = newpageids.join(','); //set, hide the modal model.set('page_ids',newpageids); modal.modal('hide'); //re-render this model el.remove(); BHM.renderHelp(model); var newel = getElForHelp(model); //mark as needing saved newel.find('.saveHelp').addClass('btn-warning'); //make sure at least the first model is visible if (!newel.first().is(':visible')) { newel.first().closest('.panel').find('.panel-title').children('a').click(); } }) } }(jQuery)); // Prevent bootstrap dialog from blocking focusin - necessary for CKEDITOR $(document).on('focusin', function(e) { if ($(e.target).closest(".cke_dialog_body").length) { e.stopImmediatePropagation(); } });