app/assets/javascripts/katello/widgets/path_selector.js
/**
* @param div_id - id of div to house env_selector
* @param name - the name of this env selector ( in case there is more than one)
* @param environments - array of environment paths
* each path being an array of hashes
* containing 'id', 'name', 'selectable' (optional)
* @param options_in
* inline (false) - Add all the paths inline, instead of a hidable panel
* select_mode (none) - selection mode ('single', 'none', 'multi')
* link_first (true) - if select_mode is not none, all the first nodes
* in the path are 'linked' so checking one checks all
* submit_button_text (none) - if set, a button is rendered with the specified text,
* clicking the button generates a message
* submit_event (path_#{name}) - if button exists, clicking it will trigger this event
* if no button and not inline, hovering out will trigger this event
* expand (true) - enable/disable the expanding of path nodes (disable for debugging)
*
*/
KT.path_select = function(div_id, name, environments, options_in){
var div,
scroll_obj,
paths_id,
path_selector,
options = {},
utils = KT.utils,
init = function(){
div = $('#' + KT.common.escapeId(div_id));
paths_id = "path_select_" + name;
options.inline = default_opt(options_in.inline, false);
options.activate_on_click = default_opt(options_in.activate_on_click, false);
options.select_mode = default_opt(options_in.select_mode, 'none');
options.submit_button_text = default_opt(options_in.submit_button_text, undefined);
options.cancel_button_text = default_opt(options_in.cancel_button_text, undefined);
options.submit_event = default_opt(options_in.submit_event, ('submit_paths_' + name));
options.cancel_event = default_opt(options_in.cancel_event, ('cancel_paths_' + name));
options.select_event = default_opt(options_in.select_event, ('selected_cell_' + name));
options.link_first = default_opt(options_in.link_first, true);
options.expand = default_opt(options_in.expand, true);
options.footer = default_opt(options_in.footer, false);
options.readonly = default_opt(options_in.readonly, false);
options.selected = default_opt(options_in.selected, undefined);
$(div).append(KT.path_select_template.selector(environments, paths_id, options.submit_button_text, options.cancel_button_text, options.footer));
path_selector = $("#" + paths_id);
path_selector.find('.node_select').not(':checked').hide();
if(options.select_mode !== 'none'){
setup_input_actions();
}
if(options.submit_button_text){
path_selector.find('.KT_path_select_submit_button').click(function(e){
if(!options.inline) {
path_selector.hide();
}
$(document).trigger(options.submit_event, [get_selected()]);
});
}
if(options.cancel_button_text){
path_selector.find('.KT_path_select_cancel_button').click(function(e){
clear_selected();
if(!options.inline) {
path_selector.hide();
}
$(document).trigger(options.cancel_event);
return false;
});
}
if(!options.inline){
path_selector.addClass("hover_selector");
path_selector.hide();
if(options.activate_on_click) {
div.click(function(e) { path_selector.show(); });
} else {
div.hoverIntent({
over:function(){ path_selector.show(); },
timeout:500,
interval: 200,
out:hover_out
});
}
}
if (options.selected) {
select(options.selected);
}
if (options.readonly) {
disable_all();
}
$(document).mouseup(function(e){
if(path_selector.has(e.target).length === 0 && !options.inline) {
path_selector.hide();
}
});
scroll_obj = KT.env_select_scroll({});
recalc_scroll();
},
reposition_left = function(){
var selector_width, pos;
if(options.inline){
return false;
}
//This is a hack for IE, sadly
path_selector.css('visibility', 'hidden');
path_selector.show();
selector_width = path_selector.outerWidth();
pos = div.outerWidth() - selector_width - 1;
path_selector.css('left', pos + 'px');
path_selector.hide();
path_selector.css('visibility', 'visible');
},
hover_out = function(){
path_selector.hide();
$(document).trigger(options.submit_event, [get_selected()]);
};
reposition_right = function(){
var margin = 10,
window_width, selector_width, button_start, pos, top;
if(options.inline){
return false;
}
window_width = $(window).width();
selector_width = path_selector.outerWidth() ;
button_start = div.offset().left;
if(button_start + selector_width + margin > window_width){
pos = window_width - (selector_width + margin);
pos = pos - button_start;
}
else{
pos = 0;
}
path_selector.css('left', pos + 'px');
},
default_opt = function(attribute, default_value){
return attribute === undefined ? default_value : attribute;
},
setup_input_actions = function(){
var anchors = path_selector.find('li'),
nodes = path_selector.find('.node_select'),
first_nodes = path_selector.find('ul').find('li:first'),
on_select, on_deselect;
anchors.hover(
function(){
var input = $(this).find('.node_select');
if (!input.is(':visible')){
input.show();
}
},
function(){
var input = $(this).find('.node_select');
if(!input.is(":checked")){
input.hide();
}
}
);
on_select = function(select_elem, fire_event){
select_nodes(select_elem);
if(options.select_mode === 'single'){
unselect_nodes(nodes);
select_nodes(select_elem);
}
if(options.link_first && select_elem.parents('li').is(':first-child')){
select_nodes(first_nodes.find('input:checkbox').not(':checked'));
}
if (fire_event !== false) {
$(document).trigger(options.select_event, [true, $(this).data('node_id'), $(this).data('next_node_id')]);
}
};
on_deselect = function(select_elem){
unselect_nodes(select_elem);
if(options.select_mode === 'single'){
nodes.removeAttr('disabled');
}
if(options.link_first && select_elem.parents('li').is(':first-child')){
unselect_nodes(first_nodes.find('input:checkbox:checked').hide());
}
$(document).trigger(options.select_event, [false, $(this).data('node_id'), $(this).data('next_node_id')]);
};
nodes.change(function(){
if ($(this).is(':checked')) {
on_select($(this));
} else {
on_deselect($(this));
}
});
},
select_nodes = function(checkbox_list){
var checkbox;
checkbox = checkbox_list.prop('checked', true).attr('checked', 'checked').show();
checkbox_list.parents('label').addClass('active');
if (options.select_mode === 'single') {
checkbox.attr('disabled', 'disabled');
}
},
unselect_nodes = function(checkbox_list){
checkbox_list.removeAttr('checked').removeAttr('disabled');
checkbox_list.parents('label').removeClass('active');
},
disable_all = function() {
path_selector.find('input:checkbox').attr('disabled', 'disabled');
},
enable_all = function() {
path_selector.find('input:checkbox').removeAttr('disabled');
},
get_selected = function(){
var selected = path_selector.find('input:checked'),
to_ret = {};
KT.utils.each(selected, function(item){
var data = $(item).data();
if(!options.link_first || to_ret[data.node_id] === undefined){
to_ret[data.node_id] = { 'id' : data.node_id, name:data.node_name,
next_id:data.next_node_id};
}
});
return to_ret;
},
get_paths = function(){
var flattened = utils.flatten(environments),
tmp_hash = {};
if (options.link_first){
KT.utils.each(flattened, function(item){
tmp_hash[item.id] = item;
});
return KT.utils.values(tmp_hash);
}
else{
return flattened;
}
},
recalc_scroll = function(){
if(!options.expand){
return false;
}
if(!options.inline){
path_selector.show();
scroll_obj.bind('#' + KT.common.escapeId(paths_id));
path_selector.hide();
}
else {
scroll_obj.bind('#' + KT.common.escapeId(paths_id));
}
},
get_submit_event = function(){
return options.submit_event;
},
get_cancel_event = function(){
return options.cancel_event;
},
get_select_event = function(){
return options.select_event;
},
clear_selected = function(){
path_selector.find('input:disabled').removeAttr('disabled');
unselect_nodes(path_selector.find('input:checked').hide());
},
set_selected = function(id) {
var nodes = path_selector.find('.node_select'),
first_nodes = path_selector.find('ul').find('li:first'),
selected_node = path_selector.find('input:checkbox[data-node_id=' + id + ']');
select_nodes(selected_node);
if(options.select_mode === 'single'){
unselect_nodes(nodes);
select_nodes(selected_node);
}
if(options.link_first && selected_node.parents('li').is(':first-child')){
select_nodes(first_nodes.find('input:checkbox').not(':checked'));
}
},
select = function(id, next_id){
var nodes = path_selector.find('input:checkbox[data-node_id=' + id + ']');
if(nodes.length > 1 && !options.link_first){
nodes.and('[data-next_node_id=' + next_id + ']').not(':checked').click();
} else {
nodes.first().not(':checked').click();
}
};
init();
return {
get_paths : get_paths,
get_selected: get_selected,
get_submit_event : get_submit_event,
get_select_event : get_select_event,
clear_selected: clear_selected,
select:select,
set_selected: set_selected,
reposition_left: reposition_left,
paths_id: paths_id,
disable_all: disable_all,
enable_all: enable_all,
hide: function() {path_selector.hide();}
};
};
KT.path_select_template = {
selector : function(paths, div_id, submit_button_text, cancel_button_text, footer){
var html = '<div id="' + div_id + '" class="path_selector"><form>';
if(cancel_button_text){
html += '<div class="action_buttons">';
html += KT.path_select_template.button("KT_path_select_cancel_button", cancel_button_text);
}
if(submit_button_text){
html += KT.path_select_template.button("KT_path_select_submit_button", submit_button_text);
html += '</div>';
}
html += KT.path_select_template.paths(paths);
html += '</form>';
if( footer ){
html += KT.path_select_template.footer(footer);
}
html += '</div>';
return html;
},
button : function(clazz, text){
return '<input type="button" class="button ' + clazz +'" value="' + text + '">';
},
paths : function(paths){
var html ='';
KT.utils.each(paths, function(item){
html += KT.path_select_template.path(item);
});
return html ;
},
path : function(path){
var html = '';
html += '<div><ul>';
for(var i = 0; i < path.length; i += 1){
html += KT.path_select_template.path_node(path[i], path[i+1]);
}
html += '</ul></div>';
return html;
},
path_node: function(node, next){
var html = '',
next_node = next ? ('data-next_node_id="' + next.id + '"') : '',
input = node.select ? '<span class="checkbox_holder"><input class="node_select" type="checkbox" ' +
next_node +' data-node_id="' + node.id + '" data-node_name="' + node.name + '"></span>' : '';
html += '<li data-node_id="' + node.id + '">'+ '<label><div>' + input + node.name + '</div></label></li>';
return html;
},
footer : function(content){
var html = '<footer>' + content + '</footer>';
return html;
}
};