Remember port search columns/settings in a Cookie
Squashed commit of the following: commit5bb8dc3bc1Author: Oliver Gorwits <oliver@cpan.org> Date: Thu Sep 5 23:48:04 2013 +0100 parse cookie and set column defaults commit05e6acfee5Author: Oliver Gorwits <oliver@cpan.org> Date: Tue Sep 3 07:12:00 2013 +0100 add list of cols to cookie commit7c5c1b7882Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Sep 2 23:23:48 2013 +0100 submit cookie with port columns options commitf350c34074Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Sep 2 22:46:14 2013 +0100 remove unecessary JS using template var commit7ca1623d2fAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Sep 2 22:35:36 2013 +0100 factor out tab-specific stuff to common.js
This commit is contained in:
		| @@ -36,6 +36,7 @@ requires 'Starman' => 0.3008; | ||||
| requires 'SNMP::Info' => 3.05; | ||||
| requires 'SQL::Translator' => 0.11016; | ||||
| requires 'Template' => 2.24; | ||||
| requires 'URL::Encode' => 0.01; | ||||
| requires 'YAML' => 0.84; | ||||
| requires 'YAML::XS' => 0.41; | ||||
| requires 'namespace::clean' => 0.24; | ||||
|   | ||||
| @@ -4,6 +4,7 @@ use Dancer ':syntax'; | ||||
| use Dancer::Plugin::Ajax; | ||||
| use Dancer::Plugin::DBIC; | ||||
| use Dancer::Plugin::Auth::Extensible; | ||||
| use URL::Encode 'url_params_mixed'; | ||||
|  | ||||
| hook 'before' => sub { | ||||
|   my @default_port_columns_left = ( | ||||
| @@ -53,6 +54,36 @@ hook 'before' => sub { | ||||
|   return unless (request->path eq uri_for('/device')->path | ||||
|     or index(request->path, uri_for('/ajax/content/device')->path) == 0); | ||||
|  | ||||
|   # override ports form defaults with cookie settings | ||||
|  | ||||
|   my $cookie = cookie('nd_ports-form'); | ||||
|   my $cdata = url_params_mixed($cookie); | ||||
|  | ||||
|   if ($cdata and ref {} eq ref $cdata) { | ||||
|       foreach my $item (@{ var('port_columns') }) { | ||||
|           my $key = $item->{name}; | ||||
|           next unless defined $cdata->{$key} | ||||
|             and $cdata->{$key} =~ m/^[[:alnum:]_]+$/; | ||||
|           $item->{default} = $cdata->{$key}; | ||||
|       } | ||||
|  | ||||
|       foreach my $item (@{ var('connected_properties') }) { | ||||
|           my $key = $item->{name}; | ||||
|           next unless defined $cdata->{$key} | ||||
|             and $cdata->{$key} =~ m/^[[:alnum:]_]+$/; | ||||
|           $item->{default} = $cdata->{$key}; | ||||
|       } | ||||
|  | ||||
|       foreach my $key (qw/age_num age_unit mac_format/) { | ||||
|           params->{$key} ||= $cdata->{$key} | ||||
|             if defined $cdata->{$key} | ||||
|                and $cdata->{$key} =~ m/^[[:alnum:]_]+$/; | ||||
|       } | ||||
|   } | ||||
|  | ||||
|   # copy ports form defaults into request query params if this is | ||||
|   # a redirect from within the application (tab param is not set) | ||||
|  | ||||
|   foreach my $col (@{ var('port_columns') }) { | ||||
|       next unless $col->{default} eq 'on'; | ||||
|       params->{$col->{name}} = 'checked' | ||||
| @@ -66,9 +97,9 @@ hook 'before' => sub { | ||||
|   } | ||||
|  | ||||
|   if (not param('tab') or param('tab') ne 'ports') { | ||||
|       params->{'age_num'} = 3; | ||||
|       params->{'age_unit'} = 'months'; | ||||
|       params->{'mac_format'} = 'IEEE'; | ||||
|       params->{'age_num'} ||= 3; | ||||
|       params->{'age_unit'} ||= 'months'; | ||||
|       params->{'mac_format'} ||= 'IEEE'; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -76,12 +107,13 @@ hook 'before_template' => sub { | ||||
|   my $tokens = shift; | ||||
|  | ||||
|   # new searches will use these defaults in their sidebars | ||||
|   $tokens->{device_ports} = uri_for('/device', { | ||||
|     tab => 'ports', | ||||
|     age_num => 3, | ||||
|     age_unit => 'months', | ||||
|     mac_format => 'IEEE', | ||||
|   }); | ||||
|   $tokens->{device_ports} = uri_for('/device', { tab => 'ports' }); | ||||
|  | ||||
|   # copy ports form defaults into helper values for building template links | ||||
|  | ||||
|   foreach my $key (qw/age_num age_unit mac_format/) { | ||||
|       $tokens->{device_ports}->query_param($key, params->{$key}); | ||||
|   } | ||||
|  | ||||
|   # for Net::MAC method | ||||
|   $tokens->{mac_format_call} = 'as_'. params->{'mac_format'} | ||||
| @@ -121,7 +153,10 @@ get '/device' => require_login sub { | ||||
|     } | ||||
|  | ||||
|     params->{'tab'} ||= 'details'; | ||||
|     template 'device', { d => $dev }; | ||||
|     template 'device', { | ||||
|       d => $dev, | ||||
|       device => params->{'tab'}, | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| true; | ||||
|   | ||||
| @@ -105,6 +105,7 @@ get '/search' => require_login sub { | ||||
|     my $vendor_list = [ $s->resultset('Device')->get_distinct_col('vendor') ]; | ||||
|  | ||||
|     template 'search', { | ||||
|       search => params->{'tab'}, | ||||
|       model_list  => $model_list, | ||||
|       os_ver_list => $os_ver_list, | ||||
|       vendor_list => $vendor_list, | ||||
|   | ||||
							
								
								
									
										96
									
								
								Netdisco/share/public/javascripts/jquery.cookie.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								Netdisco/share/public/javascripts/jquery.cookie.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| /*! | ||||
|  * jQuery Cookie Plugin v1.3.1 | ||||
|  * https://github.com/carhartl/jquery-cookie | ||||
|  * | ||||
|  * Copyright 2013 Klaus Hartl | ||||
|  * Released under the MIT license | ||||
|  */ | ||||
| (function (factory) { | ||||
| 	if (typeof define === 'function' && define.amd) { | ||||
| 		// AMD. Register as anonymous module. | ||||
| 		define(['jquery'], factory); | ||||
| 	} else { | ||||
| 		// Browser globals. | ||||
| 		factory(jQuery); | ||||
| 	} | ||||
| }(function ($) { | ||||
|  | ||||
| 	var pluses = /\+/g; | ||||
|  | ||||
| 	function decode(s) { | ||||
| 		if (config.raw) { | ||||
| 			return s; | ||||
| 		} | ||||
| 		return decodeURIComponent(s.replace(pluses, ' ')); | ||||
| 	} | ||||
|  | ||||
| 	function decodeAndParse(s) { | ||||
| 		if (s.indexOf('"') === 0) { | ||||
| 			// This is a quoted cookie as according to RFC2068, unescape... | ||||
| 			s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); | ||||
| 		} | ||||
|  | ||||
| 		s = decode(s); | ||||
|  | ||||
| 		try { | ||||
| 			return config.json ? JSON.parse(s) : s; | ||||
| 		} catch(e) {} | ||||
| 	} | ||||
|  | ||||
| 	var config = $.cookie = function (key, value, options) { | ||||
|  | ||||
| 		// Write | ||||
| 		if (value !== undefined) { | ||||
| 			options = $.extend({}, config.defaults, options); | ||||
|  | ||||
| 			if (typeof options.expires === 'number') { | ||||
| 				var days = options.expires, t = options.expires = new Date(); | ||||
| 				t.setDate(t.getDate() + days); | ||||
| 			} | ||||
|  | ||||
| 			value = config.json ? JSON.stringify(value) : String(value); | ||||
|  | ||||
| 			return (document.cookie = [ | ||||
| 				config.raw ? key : encodeURIComponent(key), | ||||
| 				'=', | ||||
| 				config.raw ? value : encodeURIComponent(value), | ||||
| 				options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE | ||||
| 				options.path    ? '; path=' + options.path : '', | ||||
| 				options.domain  ? '; domain=' + options.domain : '', | ||||
| 				options.secure  ? '; secure' : '' | ||||
| 			].join('')); | ||||
| 		} | ||||
|  | ||||
| 		// Read | ||||
| 		var cookies = document.cookie.split('; '); | ||||
| 		var result = key ? undefined : {}; | ||||
| 		for (var i = 0, l = cookies.length; i < l; i++) { | ||||
| 			var parts = cookies[i].split('='); | ||||
| 			var name = decode(parts.shift()); | ||||
| 			var cookie = parts.join('='); | ||||
|  | ||||
| 			if (key && key === name) { | ||||
| 				result = decodeAndParse(cookie); | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			if (!key) { | ||||
| 				result[name] = decodeAndParse(cookie); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return result; | ||||
| 	}; | ||||
|  | ||||
| 	config.defaults = {}; | ||||
|  | ||||
| 	$.removeCookie = function (key, options) { | ||||
| 		if ($.cookie(key) !== undefined) { | ||||
| 			// Must not alter options, thus extending a fresh object... | ||||
| 			$.cookie(key, '', $.extend({}, options, { expires: -1 })); | ||||
| 			return true; | ||||
| 		} | ||||
| 		return false; | ||||
| 	}; | ||||
|  | ||||
| })); | ||||
| @@ -1,30 +1,13 @@ | ||||
| // parameterised for the active tab - submits search form and injects | ||||
| // HTML response into the tab pane, or an error/empty-results message | ||||
| function do_search (event, tab) { | ||||
|   var form = '#' + tab + '_form'; | ||||
|   var form   = '#' + tab + '_form'; | ||||
|   var target = '#' + tab + '_pane'; | ||||
|   var query  = $(form).serialize(); | ||||
|  | ||||
|   // stop form from submitting normally | ||||
|   event.preventDefault(); | ||||
|  | ||||
|   // page title | ||||
|   var pgtitle = 'Netdisco'; | ||||
|   if ($('#nd_device-name').text().length) { | ||||
|     var pgtitle = $('#nd_device-name').text() +' - '+ $('#'+ tab + '_link').text(); | ||||
|   } | ||||
|  | ||||
|   // each sidebar search form has a hidden copy of the main navbar search | ||||
|   // query. when the tab query takes place, copy the navbar locally, then | ||||
|   // replicate to all other tabs. | ||||
|   if (path != 'report' && path != 'admin') { | ||||
|     if ($('#nq').val()) { | ||||
|       $(form).find("input[name=q]").val( $('#nq').val() ); | ||||
|     } | ||||
|     $('form').find("input[name=q]").each( function() { | ||||
|       $(this).val( $(form).find("input[name=q]").val() ); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   // hide or show sidebars depending on previous state, | ||||
|   // and whether the sidebar contains any content (detected by TT) | ||||
|   if (has_sidebar[tab] == 0) { | ||||
| @@ -41,21 +24,6 @@ function do_search (event, tab) { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // get the form params | ||||
|   var query = $(form).serialize(); | ||||
|  | ||||
|   // update browser search history with the new query. | ||||
|   // however if it's the same tab, this is a *replace* of the query url. | ||||
|   // and just skip this bit if it's the report or admin display. | ||||
|   if (path != 'report' && path != 'admin' && window.History && window.History.enabled) { | ||||
|     is_from_history_plugin = 1; | ||||
|     window.History.replaceState( | ||||
|       {name: tab, fields: $(form).serializeArray()}, | ||||
|       pgtitle, uri_base + '/' + path + '?' + query | ||||
|     ); | ||||
|     is_from_history_plugin = 0; | ||||
|   } | ||||
|  | ||||
|   // in case of slow data load, let the user know | ||||
|   $(target).html( | ||||
|     '<div class="span2 alert">Waiting for results...</div>' | ||||
|   | ||||
| @@ -1,22 +1,90 @@ | ||||
|   function update_page_title (tab) { | ||||
|     var pgtitle = 'Netdisco'; | ||||
|     if ($('#nd_device-name').text().length) { | ||||
|       var pgtitle = $('#nd_device-name').text() +' - '+ $('#'+ tab + '_link').text(); | ||||
|     } | ||||
|     return pgtitle; | ||||
|   } | ||||
|  | ||||
|   // update browser search history with the new query. | ||||
|   // however if it's the same tab, this is a *replace* of the query url. | ||||
|   // and just skip this bit if it's the report or admin display. | ||||
|   function update_browser_history (tab, pgtitle) { | ||||
|     var form = '#' + tab + '_form'; | ||||
|     var query = $(form).serialize(); | ||||
|  | ||||
|     if (window.History && window.History.enabled) { | ||||
|       is_from_history_plugin = 1; | ||||
|       window.History.replaceState( | ||||
|         {name: tab, fields: $(form).serializeArray()}, | ||||
|         pgtitle, uri_base + '/' + path + '?' + query | ||||
|       ); | ||||
|       is_from_history_plugin = 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // each sidebar search form has a hidden copy of the main navbar search | ||||
|   // query. when the tab query takes place, copy the navbar locally, then | ||||
|   // replicate to all other tabs. | ||||
|   function copy_navbar_to_sidebar (tab) { | ||||
|     var form = '#' + tab + '_form'; | ||||
|  | ||||
|     if ($('#nq').val()) { | ||||
|       $(form).find("input[name=q]").val( $('#nq').val() ); | ||||
|     } | ||||
|     $('form').find("input[name=q]").each( function() { | ||||
|       $(this).val( $(form).find("input[name=q]").val() ); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   $(document).ready(function() { | ||||
|     [% IF search %] | ||||
|     // search tabs | ||||
|     [% FOREACH tab IN settings._search_tabs %] | ||||
|     $('[% "#${tab.tag}_form" %]').submit(function(event){ do_search(event, '[% tab.tag %]'); }); | ||||
|     $('[% "#${tab.tag}_form" %]').submit(function (event) { | ||||
|       var pgtitle = update_page_title('[% tab.tag %]'); | ||||
|       update_browser_history('[% tab.tag %]', pgtitle); | ||||
|       copy_navbar_to_sidebar('[% tab.tag %]'); | ||||
|       do_search(event, '[% tab.tag %]'); | ||||
|     }); | ||||
|     [% END %] | ||||
|     [% END %] | ||||
|  | ||||
|     [% IF device %] | ||||
|     // device tabs | ||||
|     [% FOREACH tab IN settings._device_tabs %] | ||||
|     $('[% "#${tab.tag}_form" %]').submit(function(event){ do_search(event, '[% tab.tag %]'); }); | ||||
|     $('[% "#${tab.tag}_form" %]').submit(function (event) { | ||||
|       var pgtitle = update_page_title('[% tab.tag %]'); | ||||
|       update_browser_history('[% tab.tag %]', pgtitle); | ||||
|       copy_navbar_to_sidebar('[% tab.tag %]'); | ||||
|       [% IF tab.tag == 'ports' %] | ||||
|       var cookie = $('#ports_form').find('input,select') | ||||
|         .not('#nd_port-query,input[name="q"],input[name="tab"]') | ||||
|         .serializeArray(); | ||||
|       $('#ports_form').find('input[type="checkbox"]').map(function() { | ||||
|         cookie.push({'name': 'columns', 'value': $(this).attr('name')}); | ||||
|       }); | ||||
|       $.cookie('nd_ports-form', $.param(cookie) ,{ expires: 365 }); | ||||
|       [% END %] | ||||
|       do_search(event, '[% tab.tag %]'); | ||||
|     }); | ||||
|     [% END %] | ||||
|     [% END %] | ||||
|  | ||||
|     [% IF report %] | ||||
|     // for the report pages | ||||
|     $('[% "#${report.tag}_form" %]').submit(function(event){ do_search(event, '[% report.tag %]'); }); | ||||
|     $('[% "#${report.tag}_form" %]').submit(function (event) { | ||||
|       update_page_title('[% tab.tag %]'); | ||||
|       do_search(event, '[% report.tag %]'); | ||||
|     }); | ||||
|     [% END -%] | ||||
|  | ||||
|     [% IF task %] | ||||
|     // for the admin pages | ||||
|     $('[% "#${task.tag}_form" %]').submit(function(event){ do_search(event, '[% task.tag %]'); }); | ||||
|     $('[% "#${task.tag}_form" %]').submit(function (event) { | ||||
|       update_page_title('[% tab.tag %]'); | ||||
|       do_search(event, '[% task.tag %]'); | ||||
|     }); | ||||
|     [% END %] | ||||
|  | ||||
|     // on page load, load the content for the active tab | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| <!--  <script type="text/javascript" src="http://code.jquery.com/jquery-migrate-1.1.1.js"></script> --> | ||||
|   <script type="text/javascript" src="[% uri_base %]/javascripts/jquery-ui.custom.min.js"></script> | ||||
|   <script type="text/javascript" src="[% uri_base %]/javascripts/jquery-history.js"></script> | ||||
|   <script type="text/javascript" src="[% uri_base %]/javascripts/jquery.cookie.js"></script> | ||||
|   <script type="text/javascript" src="[% uri_base %]/javascripts/jquery-deserialize.js"></script> | ||||
|   <script type="text/javascript" src="[% uri_base %]/javascripts/bootstrap.min.js"></script> | ||||
|   <script type="text/javascript" src="[% uri_base %]/javascripts/underscore.min.js"></script> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user