File renamed without changes.

Large diffs are not rendered by default.

@@ -1,48 +1,48 @@
/* global Shiny */
/* global Shiny */

// tabItemInputBinding
// ------------------------------------------------------------------
// Based on Shiny.tabItemInputBinding, but customized for tabItems in
// shinydashboard, which have a slightly different structure.
var tabItemInputBinding = new Shiny.InputBinding();
$.extend(tabItemInputBinding, {
find: function(scope) {
return $(scope).find('ul.sidebar-menu');
},
getValue: function(el) {
var anchor = $(el).find('li:not(.treeview).active').children('a');
if (anchor.length === 1)
return this._getTabName(anchor);
// tabItemInputBinding
// ------------------------------------------------------------------
// Based on Shiny.tabItemInputBinding, but customized for tabItems in
// shinydashboard, which have a slightly different structure.
var tabItemInputBinding = new Shiny.InputBinding();
$.extend(tabItemInputBinding, {
find: function(scope) {
return $(scope).find('ul.sidebar-menu');
},
getValue: function(el) {
var anchor = $(el).find('li:not(.treeview).active').children('a');
if (anchor.length === 1)
return this._getTabName(anchor);

return null;
},
setValue: function(el, value) {
var self = this;
var anchors = $(el).find('li:not(.treeview)').children('a');
anchors.each(function() {
if (self._getTabName($(this)) === value) {
$(this).tab('show');
return false;
}
});
},
receiveMessage: function(el, data) {
if (data.hasOwnProperty('value'))
this.setValue(el, data.value);
},
subscribe: function(el, callback) {
// This event is triggered by deactivateOtherTabs, which is triggered by
// shown. The deactivation of other tabs must occur before Shiny gets the
// input value.
$(el).on('change.tabItemInputBinding', function() {
callback();
});
},
unsubscribe: function(el) {
$(el).off('.tabItemInputBinding');
},
_getTabName: function(anchor) {
return anchor.attr('data-value');
}
});
Shiny.inputBindings.register(tabItemInputBinding, 'shinydashboard.tabItemInput');
return null;
},
setValue: function(el, value) {
var self = this;
var anchors = $(el).find('li:not(.treeview)').children('a');
anchors.each(function() { // eslint-disable-line consistent-return
if (self._getTabName($(this)) === value) {
$(this).tab('show');
return false;
}
});
},
receiveMessage: function(el, data) {
if (data.hasOwnProperty('value'))
this.setValue(el, data.value);
},
subscribe: function(el, callback) {
// This event is triggered by deactivateOtherTabs, which is triggered by
// shown. The deactivation of other tabs must occur before Shiny gets the
// input value.
$(el).on('change.tabItemInputBinding', function() {
callback();
});
},
unsubscribe: function(el) {
$(el).off('.tabItemInputBinding');
},
_getTabName: function(anchor) {
return anchor.attr('data-value');
}
});
Shiny.inputBindings.register(tabItemInputBinding, 'shinydashboard.tabItemInput');
@@ -1,45 +1,45 @@
/* global Shiny */
/* global Shiny */

// menuOutputBinding
// ------------------------------------------------------------------
// Based on Shiny.htmlOutputBinding, but instead of putting the result in a
// wrapper div, it replaces the origin DOM element with the new DOM elements,
// copying over the ID and class.
var menuOutputBinding = new Shiny.OutputBinding();
$.extend(menuOutputBinding, {
find: function(scope) {
return $(scope).find('.shinydashboard-menu-output');
},
onValueError: function(el, err) {
Shiny.unbindAll(el);
this.renderError(el, err);
},
renderValue: function(el, data) {
Shiny.unbindAll(el);
// menuOutputBinding
// ------------------------------------------------------------------
// Based on Shiny.htmlOutputBinding, but instead of putting the result in a
// wrapper div, it replaces the origin DOM element with the new DOM elements,
// copying over the ID and class.
var menuOutputBinding = new Shiny.OutputBinding();
$.extend(menuOutputBinding, {
find: function(scope) {
return $(scope).find('.shinydashboard-menu-output');
},
onValueError: function(el, err) {
Shiny.unbindAll(el);
this.renderError(el, err);
},
renderValue: function(el, data) {
Shiny.unbindAll(el);

var html;
var dependencies = [];
if (data === null) {
return;
} else if (typeof(data) === 'string') {
html = data;
} else if (typeof(data) === 'object') {
html = data.html;
dependencies = data.deps;
}
var html;
var dependencies = [];
if (data === null) {
return;
} else if (typeof(data) === 'string') {
html = data;
} else if (typeof(data) === 'object') {
html = data.html;
dependencies = data.deps;
}

var $html = $($.parseHTML(html));
var $html = $($.parseHTML(html));

// Convert the inner contents to HTML, and pass to renderHtml
Shiny.renderHtml($html.html(), el, dependencies);
// Convert the inner contents to HTML, and pass to renderHtml
Shiny.renderHtml($html.html(), el, dependencies);

// Extract class of wrapper, and add them to the wrapper element
el.className = 'shinydashboard-menu-output shiny-bound-output ' +
$html.attr('class');
// Extract class of wrapper, and add them to the wrapper element
el.className = 'shinydashboard-menu-output shiny-bound-output ' +
$html.attr('class');

Shiny.initializeInputs(el);
Shiny.bindAll(el);
}
});
Shiny.outputBindings.register(menuOutputBinding,
"shinydashboard.menuOutputBinding");
Shiny.initializeInputs(el);
Shiny.bindAll(el);
}
});
Shiny.outputBindings.register(menuOutputBinding,
"shinydashboard.menuOutputBinding");
@@ -1,15 +1,15 @@
// Optionally disable sidebar
if ($("section.sidebar").data("disable")) {
$("body").addClass("sidebar-collapse");
$(".navbar > .sidebar-toggle").hide();
}
// Optionally disable sidebar
if ($("section.sidebar").data("disable")) {
$("body").addClass("sidebar-collapse");
$(".navbar > .sidebar-toggle").hide();
}

// Trigger the resize event when the sidebar is collapsed/expanded
// (this allows images to be responsive and resize themselves)
$(document).on("click", ".sidebar-toggle", function() {
$(window).trigger("resize");
});
// Trigger the resize event when the sidebar is collapsed/expanded
// (this allows images to be responsive and resize themselves)
$(document).on("click", ".sidebar-toggle", function() {
$(window).trigger("resize");
});

$(document).on("click", ".treeview > a", function() {
$(this).next(".treeview-menu").trigger("shown");
});
$(document).on("click", ".treeview > a", function() {
$(this).next(".treeview-menu").trigger("shown");
});
@@ -1,46 +1,46 @@
// This function handles a special case in the AdminLTE sidebar: when there
// is a sidebar-menu with items, and one of those items has sub-items, and
// they are used for tab navigation. Normally, if one of the items is
// selected and then a sub-item is clicked, both the item and sub-item will
// retain the "active" class, so they will both be highlighted. This happens
// because they're not designed to be used together for tab panels. This
// code ensures that only one item will have the "active" class.
var deactivateOtherTabs = function() {
var $this = $(this);
var $sidebarMenu = $this.closest("ul.sidebar-menu");

// Find all tab links under sidebar-menu
var $tablinks = $sidebarMenu.find("a[data-toggle='tab']");

// If any other items are active, deactivate them
$tablinks.not($this).parent("li").removeClass("active");

// Trigger event for the tabItemInputBinding
$sidebarMenu.trigger('change.tabItemInputBinding');
};

$(document).on('shown.bs.tab', '.sidebar-menu a[data-toggle="tab"]',
deactivateOtherTabs);


// When document is ready, if there is a sidebar menu with no activated tabs,
// activate the one specified by `data-start-selected`, or if that's not
// present, the first one.
var ensureActivatedTab = function() {
var $tablinks = $("ul.sidebar-menu").find("a").filter("[data-toggle='tab']");

// If there's a `data-start-selected` attribute and we can find a tab with
// that name, activate it.
var $startTab = $tablinks.filter("[data-start-selected='1']");
if ($startTab.length !== 0) {
$startTab.tab("show");
return;
}

// If we got this far, just activate the first tab.
if (! $tablinks.parent("li").hasClass("active") ) {
$tablinks.first().tab("show");
}
};

ensureActivatedTab();
// This function handles a special case in the AdminLTE sidebar: when there
// is a sidebar-menu with items, and one of those items has sub-items, and
// they are used for tab navigation. Normally, if one of the items is
// selected and then a sub-item is clicked, both the item and sub-item will
// retain the "active" class, so they will both be highlighted. This happens
// because they're not designed to be used together for tab panels. This
// code ensures that only one item will have the "active" class.
var deactivateOtherTabs = function() {
var $this = $(this);
var $sidebarMenu = $this.closest("ul.sidebar-menu");

// Find all tab links under sidebar-menu
var $tablinks = $sidebarMenu.find("a[data-toggle='tab']");

// If any other items are active, deactivate them
$tablinks.not($this).parent("li").removeClass("active");

// Trigger event for the tabItemInputBinding
$sidebarMenu.trigger('change.tabItemInputBinding');
};

$(document).on('shown.bs.tab', '.sidebar-menu a[data-toggle="tab"]',
deactivateOtherTabs);


// When document is ready, if there is a sidebar menu with no activated tabs,
// activate the one specified by `data-start-selected`, or if that's not
// present, the first one.
var ensureActivatedTab = function() {
var $tablinks = $("ul.sidebar-menu").find("a").filter("[data-toggle='tab']");

// If there's a `data-start-selected` attribute and we can find a tab with
// that name, activate it.
var $startTab = $tablinks.filter("[data-start-selected='1']");
if ($startTab.length !== 0) {
$startTab.tab("show");
return;
}

// If we got this far, just activate the first tab.
if (! $tablinks.parent("li").hasClass("active") ) {
$tablinks.first().tab("show");
}
};

ensureActivatedTab();
@@ -7,6 +7,23 @@ module.exports = function(grunt) {

grunt.initConfig({
pkg: pkgInfo(),

clean: {
options: { force: true },
src: [
destdirjs + "shinydashboard.js",
destdirjs + "shinydashboard.js.map",
destdirjs + "shinydashboard.min.js",
destdirjs + "shinydashboard.min.js.map",
destdirjs + "AdminLTE/app.js",
destdirjs + "AdminLTE/app.js.map",
destdirjs + "AdminLTE/app.min.js",
destdirjs + "AdminLTE/app.min.js.map",
destdircss + "AdminLTE/AdminLTE.min.css",
destdircss + "AdminLTE/_all-skins.min.css",
]
},

concat: {
options: {
process: function(src, filepath) {
@@ -25,43 +42,79 @@ module.exports = function(grunt) {
srcdirjs + '_end.js'
],
dest: destdirjs + 'shinydashboard.js'
},
adminlte: {
src: [
srcdirjs + 'AdminLTE/app.js'
],
dest: destdirjs + 'AdminLTE/app.js'
}
},

uglify: {
shinydashboard: {
options: {
banner: '/*! <%= pkg.name %> <%= pkg.version %> | ' +
'(c) 2017-<%= grunt.template.today("yyyy") %> RStudio, Inc. | ' +
'License: <%= pkg.license %> */\n',
sourceMap: true,
// Base the .min.js sourcemap off of the .js sourcemap created by concat
sourceMapIn: destdirjs + 'shinydashboard.js.map',
sourceMapIncludeSources: true
},
src: destdirjs + 'shinydashboard.js',
dest: destdirjs + 'shinydashboard.min.js'
},
adminlte: {
options: {
sourceMap: true
},
src: destdirjs + '/AdminLTE/app.js',
dest: destdirjs + '/AdminLTE/app.min.js'
src: srcdirjs + 'AdminLTE/app.js',
dest: destdirjs + 'AdminLTE/app.min.js'
}
},

cssmin: {
adminlte: {
src: srcdircss + '/AdminLTE/AdminLTE.css',
dest: srcdircss + '/AdminLTE/AdminLTE.min.css'
src: srcdircss + 'AdminLTE/AdminLTE.css',
dest: destdircss + 'AdminLTE/AdminLTE.min.css'
},
adminlte_themes: {
src: srcdircss + '/AdminLTE/_all-skins.css',
dest: srcdircss + '/AdminLTE/_all-skins.min.css'
src: srcdircss + 'AdminLTE/_all-skins.css',
dest: destdircss + 'AdminLTE/_all-skins.min.css'
}
},

jshint: {
eslint: {
options: {
force: true // Don't abort if there are JSHint warnings
extends: 'eslint:recommended',
rules: {
"consistent-return": 1,
"dot-location": [1, "property"],
"eqeqeq": 1,
"no-undef": 1,
"no-unused-vars": [1, {"args": "none"}],
"guard-for-in": 1,
"semi": [1, "always"]
},
envs: [
"browser",
"jquery"
],
globals: ["strftime"]
},
shinydashboard: {
src: destdirjs + '/shinydashboard.js',
}
shinydashboard: [
srcdirjs + 'tabs.js',
srcdirjs + 'sidebar.js',
srcdirjs + 'output_binding_menu.js',
srcdirjs + 'input_binding_tabItem.js',
]
},

watch: {
shinydashboard: {
files: '<%= jshint.shinydashboard.src %>',
tasks: ['newer:jshint:shinydashboard']
files: '<%= concat.shinydashboard.src %>',
tasks: ['newer:concat:shinydashboard', 'newer:uglify:shinydashboard', 'newer:jshint:shinydashboard']
},
adminlte: {
files: ['<%= uglify.adminlte.src %>', '<%= cssmin.adminlte.src %>'],
@@ -70,18 +123,19 @@ module.exports = function(grunt) {
}
});


grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-newer');


grunt.registerTask('default', ['newer:concat', 'newer:uglify', 'newer:cssmin', 'newer:jshint']);
grunt.registerTask('default', ['newer:concat', 'newer:eslint', 'newer:uglify', 'newer:cssmin']);


// ---------------------------------------------------------------------------
// Utility functions
// ---------------------------------------------------------------------------

// Return an object which merges information from package.json and the
// DESCRIPTION file.
@@ -113,4 +167,3 @@ module.exports = function(grunt) {
return txt;
}
};

@@ -6,6 +6,7 @@
"grunt-contrib-jshint": "^1.1.0",
"grunt-contrib-uglify": "^2.1.0",
"grunt-contrib-watch": "^1.0.0",
"grunt-eslint": "^19.0.0",
"grunt-newer": "^1.2.0"
}
}

Large diffs are not rendered by default.