Major overhaul for standalone operation.
This removes some of the `edbob` reliance, as well as borrowing some templates and styling etc. from Dtail.
This commit is contained in:
		
							parent
							
								
									b9f61e6a47
								
							
						
					
					
						commit
						2a50e704ef
					
				
					 59 changed files with 1969 additions and 39 deletions
				
			
		
							
								
								
									
										5
									
								
								tailbone/static/js/lib/jquery-1.9.1.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tailbone/static/js/lib/jquery-1.9.1.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										6
									
								
								tailbone/static/js/lib/jquery-ui-1.10.0.custom.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tailbone/static/js/lib/jquery-ui-1.10.0.custom.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										10
									
								
								tailbone/static/js/lib/jquery.loadmask.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tailbone/static/js/lib/jquery.loadmask.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| /** | ||||
|  * Copyright (c) 2009 Sergiy Kovalchuk (serg472@gmail.com) | ||||
|  *  | ||||
|  * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 | ||||
|  * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 | ||||
|  *   | ||||
|  * Following code is based on Element.mask() implementation from ExtJS framework (http://extjs.com/)
 | ||||
|  * | ||||
|  */ | ||||
| (function(a){a.fn.mask=function(c,b){a(this).each(function(){if(b!==undefined&&b>0){var d=a(this);d.data("_mask_timeout",setTimeout(function(){a.maskElement(d,c)},b))}else{a.maskElement(a(this),c)}})};a.fn.unmask=function(){a(this).each(function(){a.unmaskElement(a(this))})};a.fn.isMasked=function(){return this.hasClass("masked")};a.maskElement=function(d,c){if(d.data("_mask_timeout")!==undefined){clearTimeout(d.data("_mask_timeout"));d.removeData("_mask_timeout")}if(d.isMasked()){a.unmaskElement(d)}if(d.css("position")=="static"){d.addClass("masked-relative")}d.addClass("masked");var e=a('<div class="loadmask"></div>');if(navigator.userAgent.toLowerCase().indexOf("msie")>-1){e.height(d.height()+parseInt(d.css("padding-top"))+parseInt(d.css("padding-bottom")));e.width(d.width()+parseInt(d.css("padding-left"))+parseInt(d.css("padding-right")))}if(navigator.userAgent.toLowerCase().indexOf("msie 6")>-1){d.find("select").addClass("masked-hidden")}d.append(e);if(c!==undefined){var b=a('<div class="loadmask-msg" style="display:none;"></div>');b.append("<div>"+c+"</div>");d.append(b);b.css("top",Math.round(d.height()/2-(b.height()-parseInt(b.css("padding-top"))-parseInt(b.css("padding-bottom")))/2)+"px");b.css("left",Math.round(d.width()/2-(b.width()-parseInt(b.css("padding-left"))-parseInt(b.css("padding-right")))/2)+"px");b.show()}};a.unmaskElement=function(b){if(b.data("_mask_timeout")!==undefined){clearTimeout(b.data("_mask_timeout"));b.removeData("_mask_timeout")}b.find(".loadmask-msg,.loadmask").remove();b.removeClass("masked");b.removeClass("masked-relative");b.find("select").removeClass("masked-hidden")}})(jQuery); | ||||
							
								
								
									
										327
									
								
								tailbone/static/js/lib/jquery.ui.menubar.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								tailbone/static/js/lib/jquery.ui.menubar.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,327 @@ | |||
| /* | ||||
|  * jQuery UI Menubar @VERSION | ||||
|  * | ||||
|  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 | ||||
|  * Dual licensed under the MIT or GPL Version 2 licenses. | ||||
|  * http://jquery.org/license
 | ||||
|  * | ||||
|  * http://docs.jquery.com/UI/Menubar
 | ||||
|  * | ||||
|  * Depends: | ||||
|  *	jquery.ui.core.js | ||||
|  *	jquery.ui.widget.js | ||||
|  *	jquery.ui.position.js | ||||
|  *	jquery.ui.menu.js | ||||
|  */ | ||||
| (function( $ ) { | ||||
| 
 | ||||
| // TODO when mixing clicking menus and keyboard navigation, focus handling is broken
 | ||||
| // there has to be just one item that has tabindex
 | ||||
| $.widget( "ui.menubar", { | ||||
| 	version: "@VERSION", | ||||
| 	options: { | ||||
| 		autoExpand: false, | ||||
| 		buttons: false, | ||||
| 		items: "li", | ||||
| 		menuElement: "ul", | ||||
| 		menuIcon: false, | ||||
| 		position: { | ||||
| 			my: "left top", | ||||
| 			at: "left bottom" | ||||
| 		} | ||||
| 	}, | ||||
| 	_create: function() { | ||||
| 		var that = this; | ||||
| 		this.menuItems = this.element.children( this.options.items ); | ||||
| 		this.items = this.menuItems.children( "button, a" ); | ||||
| 
 | ||||
| 		this.menuItems | ||||
| 			.addClass( "ui-menubar-item" ) | ||||
| 			.attr( "role", "presentation" ); | ||||
| 		// let only the first item receive focus
 | ||||
| 		this.items.slice(1).attr( "tabIndex", -1 ); | ||||
| 
 | ||||
| 		this.element | ||||
| 			.addClass( "ui-menubar ui-widget-header ui-helper-clearfix" ) | ||||
| 			.attr( "role", "menubar" ); | ||||
| 		this._focusable( this.items ); | ||||
| 		this._hoverable( this.items ); | ||||
| 		this.items.siblings( this.options.menuElement ) | ||||
| 			.menu({ | ||||
| 				position: { | ||||
| 					within: this.options.position.within | ||||
| 				}, | ||||
| 				select: function( event, ui ) { | ||||
| 					ui.item.parents( "ul.ui-menu:last" ).hide(); | ||||
| 					that._close(); | ||||
| 					// TODO what is this targetting? there's probably a better way to access it
 | ||||
| 					$(event.target).prev().focus(); | ||||
| 					that._trigger( "select", event, ui ); | ||||
| 				}, | ||||
| 				menus: that.options.menuElement | ||||
| 			}) | ||||
| 			.hide() | ||||
| 			.attr({ | ||||
| 				"aria-hidden": "true", | ||||
| 				"aria-expanded": "false" | ||||
| 			}) | ||||
| 			// TODO use _on
 | ||||
| 			.bind( "keydown.menubar", function( event ) { | ||||
| 				var menu = $( this ); | ||||
| 				if ( menu.is( ":hidden" ) ) { | ||||
| 					return; | ||||
| 				} | ||||
| 				switch ( event.keyCode ) { | ||||
| 				case $.ui.keyCode.LEFT: | ||||
| 					that.previous( event ); | ||||
| 					event.preventDefault(); | ||||
| 					break; | ||||
| 				case $.ui.keyCode.RIGHT: | ||||
| 					that.next( event ); | ||||
| 					event.preventDefault(); | ||||
| 					break; | ||||
| 				} | ||||
| 			}); | ||||
| 		this.items.each(function() { | ||||
| 			var input = $(this), | ||||
| 				// TODO menu var is only used on two places, doesn't quite justify the .each
 | ||||
| 				menu = input.next( that.options.menuElement ); | ||||
| 
 | ||||
| 			// might be a non-menu button
 | ||||
| 			if ( menu.length ) { | ||||
| 				// TODO use _on
 | ||||
| 				input.bind( "click.menubar focus.menubar mouseenter.menubar", function( event ) { | ||||
| 					// ignore triggered focus event
 | ||||
| 					if ( event.type === "focus" && !event.originalEvent ) { | ||||
| 						return; | ||||
| 					} | ||||
| 					event.preventDefault(); | ||||
| 					// TODO can we simplify or extractthis check? especially the last two expressions
 | ||||
| 					// there's a similar active[0] == menu[0] check in _open
 | ||||
| 					if ( event.type === "click" && menu.is( ":visible" ) && that.active && that.active[0] === menu[0] ) { | ||||
| 						that._close(); | ||||
| 						return; | ||||
| 					} | ||||
| 					if ( ( that.open && event.type === "mouseenter" ) || event.type === "click" || that.options.autoExpand ) { | ||||
| 						if( that.options.autoExpand ) { | ||||
| 							clearTimeout( that.closeTimer ); | ||||
| 						} | ||||
| 
 | ||||
| 						that._open( event, menu ); | ||||
| 					} | ||||
| 				}) | ||||
| 				// TODO use _on
 | ||||
| 				.bind( "keydown", function( event ) { | ||||
| 					switch ( event.keyCode ) { | ||||
| 					case $.ui.keyCode.SPACE: | ||||
| 					case $.ui.keyCode.UP: | ||||
| 					case $.ui.keyCode.DOWN: | ||||
| 						that._open( event, $( this ).next() ); | ||||
| 						event.preventDefault(); | ||||
| 						break; | ||||
| 					case $.ui.keyCode.LEFT: | ||||
| 						that.previous( event ); | ||||
| 						event.preventDefault(); | ||||
| 						break; | ||||
| 					case $.ui.keyCode.RIGHT: | ||||
| 						that.next( event ); | ||||
| 						event.preventDefault(); | ||||
| 						break; | ||||
| 					} | ||||
| 				}) | ||||
| 				.attr( "aria-haspopup", "true" ); | ||||
| 
 | ||||
| 				// TODO review if these options (menuIcon and buttons) are a good choice, maybe they can be merged
 | ||||
| 				if ( that.options.menuIcon ) { | ||||
| 					input.addClass( "ui-state-default" ).append( "<span class='ui-button-icon-secondary ui-icon ui-icon-triangle-1-s'></span>" ); | ||||
| 					input.removeClass( "ui-button-text-only" ).addClass( "ui-button-text-icon-secondary" ); | ||||
| 				} | ||||
| 			} else { | ||||
| 				// TODO use _on
 | ||||
| 				input.bind( "click.menubar mouseenter.menubar", function( event ) { | ||||
| 					if ( ( that.open && event.type === "mouseenter" ) || event.type === "click" ) { | ||||
| 						that._close(); | ||||
| 					} | ||||
| 				}); | ||||
| 			} | ||||
| 
 | ||||
| 			input | ||||
| 				.addClass( "ui-button ui-widget ui-button-text-only ui-menubar-link" ) | ||||
| 				.attr( "role", "menuitem" ) | ||||
| 				.wrapInner( "<span class='ui-button-text'></span>" ); | ||||
| 
 | ||||
| 			if ( that.options.buttons ) { | ||||
| 				input.removeClass( "ui-menubar-link" ).addClass( "ui-state-default" ); | ||||
| 			} | ||||
| 		}); | ||||
| 		that._on( { | ||||
| 			keydown: function( event ) { | ||||
| 				if ( event.keyCode === $.ui.keyCode.ESCAPE && that.active && that.active.menu( "collapse", event ) !== true ) { | ||||
| 					var active = that.active; | ||||
| 					that.active.blur(); | ||||
| 					that._close( event ); | ||||
| 					active.prev().focus(); | ||||
| 				} | ||||
| 			}, | ||||
| 			focusin: function( event ) { | ||||
| 				clearTimeout( that.closeTimer ); | ||||
| 			}, | ||||
| 			focusout: function( event ) { | ||||
| 				that.closeTimer = setTimeout( function() { | ||||
| 					that._close( event ); | ||||
| 				}, 150); | ||||
| 			}, | ||||
| 			"mouseleave .ui-menubar-item": function( event ) { | ||||
| 				if ( that.options.autoExpand ) { | ||||
| 					that.closeTimer = setTimeout( function() { | ||||
| 						that._close( event ); | ||||
| 					}, 150); | ||||
| 				} | ||||
| 			}, | ||||
| 			"mouseenter .ui-menubar-item": function( event ) { | ||||
| 				clearTimeout( that.closeTimer ); | ||||
| 			} | ||||
| 		}); | ||||
| 
 | ||||
| 		// Keep track of open submenus
 | ||||
| 		this.openSubmenus = 0; | ||||
| 	}, | ||||
| 
 | ||||
| 	_destroy : function() { | ||||
| 		this.menuItems | ||||
| 			.removeClass( "ui-menubar-item" ) | ||||
| 			.removeAttr( "role" ); | ||||
| 
 | ||||
| 		this.element | ||||
| 			.removeClass( "ui-menubar ui-widget-header ui-helper-clearfix" ) | ||||
| 			.removeAttr( "role" ) | ||||
| 			.unbind( ".menubar" ); | ||||
| 
 | ||||
| 		this.items | ||||
| 			.unbind( ".menubar" ) | ||||
| 			.removeClass( "ui-button ui-widget ui-button-text-only ui-menubar-link ui-state-default" ) | ||||
| 			.removeAttr( "role" ) | ||||
| 			.removeAttr( "aria-haspopup" ) | ||||
| 			// TODO unwrap?
 | ||||
| 			.children( "span.ui-button-text" ).each(function( i, e ) { | ||||
| 				var item = $( this ); | ||||
| 				item.parent().html( item.html() ); | ||||
| 			}) | ||||
| 			.end() | ||||
| 			.children( ".ui-icon" ).remove(); | ||||
| 
 | ||||
| 		this.element.find( ":ui-menu" ) | ||||
| 			.menu( "destroy" ) | ||||
| 			.show() | ||||
| 			.removeAttr( "aria-hidden" ) | ||||
| 			.removeAttr( "aria-expanded" ) | ||||
| 			.removeAttr( "tabindex" ) | ||||
| 			.unbind( ".menubar" ); | ||||
| 	}, | ||||
| 
 | ||||
| 	_close: function() { | ||||
| 		if ( !this.active || !this.active.length ) { | ||||
| 			return; | ||||
| 		} | ||||
| 		this.active | ||||
| 			.menu( "collapseAll" ) | ||||
| 			.hide() | ||||
| 			.attr({ | ||||
| 				"aria-hidden": "true", | ||||
| 				"aria-expanded": "false" | ||||
| 			}); | ||||
| 		this.active | ||||
| 			.prev() | ||||
| 			.removeClass( "ui-state-active" ) | ||||
| 			.removeAttr( "tabIndex" ); | ||||
| 		this.active = null; | ||||
| 		this.open = false; | ||||
| 		this.openSubmenus = 0; | ||||
| 	}, | ||||
| 
 | ||||
| 	_open: function( event, menu ) { | ||||
| 		// on a single-button menubar, ignore reopening the same menu
 | ||||
| 		if ( this.active && this.active[0] === menu[0] ) { | ||||
| 			return; | ||||
| 		} | ||||
| 		// TODO refactor, almost the same as _close above, but don't remove tabIndex
 | ||||
| 		if ( this.active ) { | ||||
| 			this.active | ||||
| 				.menu( "collapseAll" ) | ||||
| 				.hide() | ||||
| 				.attr({ | ||||
| 					"aria-hidden": "true", | ||||
| 					"aria-expanded": "false" | ||||
| 				}); | ||||
| 			this.active | ||||
| 				.prev() | ||||
| 				.removeClass( "ui-state-active" ); | ||||
| 		} | ||||
| 		// set tabIndex -1 to have the button skipped on shift-tab when menu is open (it gets focus)
 | ||||
| 		var button = menu.prev().addClass( "ui-state-active" ).attr( "tabIndex", -1 ); | ||||
| 		this.active = menu | ||||
| 			.show() | ||||
| 			.position( $.extend({ | ||||
| 				of: button | ||||
| 			}, this.options.position ) ) | ||||
| 			.removeAttr( "aria-hidden" ) | ||||
| 			.attr( "aria-expanded", "true" ) | ||||
| 			.menu("focus", event, menu.children( ".ui-menu-item" ).first() ) | ||||
| 			// TODO need a comment here why both events are triggered
 | ||||
| 			.focus() | ||||
| 			.focusin(); | ||||
| 		this.open = true; | ||||
| 	}, | ||||
| 
 | ||||
| 	next: function( event ) { | ||||
| 		if ( this.open && this.active.data( "menu" ).active.has( ".ui-menu" ).length ) { | ||||
| 			// Track number of open submenus and prevent moving to next menubar item
 | ||||
| 			this.openSubmenus++; | ||||
| 			return; | ||||
| 		} | ||||
| 		this.openSubmenus = 0; | ||||
| 		this._move( "next", "first", event ); | ||||
| 	}, | ||||
| 
 | ||||
| 	previous: function( event ) { | ||||
| 		if ( this.open && this.openSubmenus ) { | ||||
| 			// Track number of open submenus and prevent moving to previous menubar item
 | ||||
| 			this.openSubmenus--; | ||||
| 			return; | ||||
| 		} | ||||
| 		this.openSubmenus = 0; | ||||
| 		this._move( "prev", "last", event ); | ||||
| 	}, | ||||
| 
 | ||||
| 	_move: function( direction, filter, event ) { | ||||
| 		var next, | ||||
| 			wrapItem; | ||||
| 		if ( this.open ) { | ||||
| 			next = this.active.closest( ".ui-menubar-item" )[ direction + "All" ]( this.options.items ).first().children( ".ui-menu" ).eq( 0 ); | ||||
| 			wrapItem = this.menuItems[ filter ]().children( ".ui-menu" ).eq( 0 ); | ||||
| 		} else { | ||||
| 			if ( event ) { | ||||
| 				next = $( event.target ).closest( ".ui-menubar-item" )[ direction + "All" ]( this.options.items ).children( ".ui-menubar-link" ).eq( 0 ); | ||||
| 				wrapItem = this.menuItems[ filter ]().children( ".ui-menubar-link" ).eq( 0 ); | ||||
| 			} else { | ||||
| 				next = wrapItem = this.menuItems.children( "a" ).eq( 0 ); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if ( next.length ) { | ||||
| 			if ( this.open ) { | ||||
| 				this._open( event, next ); | ||||
| 			} else { | ||||
| 				next.removeAttr( "tabIndex")[0].focus(); | ||||
| 			} | ||||
| 		} else { | ||||
| 			if ( this.open ) { | ||||
| 				this._open( event, wrapItem ); | ||||
| 			} else { | ||||
| 				wrapItem.removeAttr( "tabIndex")[0].focus(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| }( jQuery )); | ||||
							
								
								
									
										260
									
								
								tailbone/static/js/tailbone.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								tailbone/static/js/tailbone.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,260 @@ | |||
| 
 | ||||
| /************************************************************ | ||||
|  * | ||||
|  * tailbone.js | ||||
|  * | ||||
|  ************************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
|  * Initialize the disabled filters array.  This is populated from within the | ||||
|  * /grids/search.mako template. | ||||
|  */ | ||||
| var filters_to_disable = []; | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
|  * Disables options within the "add filter" dropdown which correspond to those | ||||
|  * filters already being displayed.  Called from /grids/search.mako template. | ||||
|  */ | ||||
| function disable_filter_options() { | ||||
|     while (filters_to_disable.length) { | ||||
|         var filter = filters_to_disable.shift(); | ||||
|         var option = $('#add-filter option[value="' + filter + '"]'); | ||||
|         option.attr('disabled', 'disabled'); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
|  * Convenience function to disable a form button. | ||||
|  */ | ||||
| function disable_button(button, label) { | ||||
|     if (label) { | ||||
|         $(button).html(label + ", please wait..."); | ||||
|     } | ||||
|     $(button).attr('disabled', 'disabled'); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
|  * Load next / previous page of results to grid.  This function is called on | ||||
|  * the click event from the pager links, via inline script code. | ||||
|  */ | ||||
| function grid_navigate_page(link, url) { | ||||
|     var wrapper = $(link).parents('div.grid-wrapper'); | ||||
|     var grid = wrapper.find('div.grid'); | ||||
|     wrapper.mask("Loading..."); | ||||
|     $.get(url, function(data) { | ||||
|         wrapper.unmask(); | ||||
|         grid.replaceWith(data); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
|  * Fetch the UUID value associated with a table row. | ||||
|  */ | ||||
| function get_uuid(obj) { | ||||
|     obj = $(obj); | ||||
|     if (obj.attr('uuid')) { | ||||
|         return obj.attr('uuid'); | ||||
|     } | ||||
|     var tr = obj.parents('tr:first'); | ||||
|     if (tr.attr('uuid')) { | ||||
|         return tr.attr('uuid'); | ||||
|     } | ||||
|     return undefined; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
|  * get_dialog(id, callback) | ||||
|  * | ||||
|  * Returns a <DIV> element suitable for use as a jQuery dialog. | ||||
|  * | ||||
|  * ``id`` is used to construct a proper ID for the element and allows the | ||||
|  * dialog to be resused if possible. | ||||
|  * | ||||
|  * ``callback``, if specified, should be a callback function for the dialog. | ||||
|  * This function will be called whenever the dialog has been closed | ||||
|  * "successfully" (i.e. data submitted) by the user, and should accept a single | ||||
|  * ``data`` object which is the JSON response returned by the server. | ||||
|  */ | ||||
| 
 | ||||
| function get_dialog(id, callback) { | ||||
|     var dialog = $('#'+id+'-dialog'); | ||||
|     if (! dialog.length) { | ||||
|         dialog = $('<div class="dialog" id="'+id+'-dialog"></div>'); | ||||
|     } | ||||
|     if (callback) { | ||||
|         dialog.attr('callback', callback); | ||||
|     } | ||||
|     return dialog; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| $(function() { | ||||
| 
 | ||||
|     /* | ||||
|      * Initialize the menu bar. | ||||
|      */ | ||||
|     $('ul.menubar').menubar({ | ||||
|         buttons: true, | ||||
|         menuIcon: true, | ||||
|         autoExpand: true | ||||
|     }); | ||||
| 
 | ||||
|     /* | ||||
|      * When filter labels are clicked, (un)check the associated checkbox. | ||||
|      */ | ||||
|     $('div.grid-wrapper div.filter label').on('click', function() { | ||||
|         var checkbox = $(this).prev('input[type="checkbox"]'); | ||||
|         if (checkbox.prop('checked')) { | ||||
|             checkbox.prop('checked', false); | ||||
|             return false; | ||||
|         } | ||||
|         checkbox.prop('checked', true); | ||||
|     }); | ||||
| 
 | ||||
|     /* | ||||
|      * When a new filter is selected in the "add filter" dropdown, show it in | ||||
|      * the UI.  This selects the filter's checkbox and puts focus to its input | ||||
|      * element.  If all available filters have been displayed, the "add filter" | ||||
|      * dropdown will be hidden. | ||||
|      */ | ||||
|     $('#add-filter').on('change', function() { | ||||
|         var select = $(this); | ||||
|         var filters = select.parents('div.filters:first'); | ||||
|         var filter = filters.find('#filter-' + select.val()); | ||||
|         var checkbox = filter.find('input[type="checkbox"]:first'); | ||||
|         var input = filter.find(':last-child'); | ||||
| 
 | ||||
|         checkbox.prop('checked', true); | ||||
|         filter.show(); | ||||
|         input.select(); | ||||
|         input.focus(); | ||||
| 
 | ||||
|         filters.find('input[type="submit"]').show(); | ||||
|         filters.find('button[type="reset"]').show(); | ||||
| 
 | ||||
|         select.find('option:selected').attr('disabled', true); | ||||
|         select.val('add a filter'); | ||||
|         if (select.find('option:enabled').length == 1) { | ||||
|             select.hide(); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     /* | ||||
|      * When user clicks the grid filters search button, perform the search in | ||||
|      * the background and reload the grid in-place. | ||||
|      */ | ||||
|     $('div.filters form').submit(function() { | ||||
|         var form = $(this); | ||||
|         var wrapper = form.parents('div.grid-wrapper'); | ||||
|         var grid = wrapper.find('div.grid'); | ||||
|         var data = form.serializeArray(); | ||||
|         data.push({name: 'partial', value: true}); | ||||
|         wrapper.mask("Loading..."); | ||||
|         $.get(grid.attr('url'), data, function(data) { | ||||
|             wrapper.unmask(); | ||||
|             grid.replaceWith(data); | ||||
|         }); | ||||
|         return false; | ||||
|     }); | ||||
| 
 | ||||
|     /* | ||||
|      * When user clicks the grid filters reset button, manually clear all | ||||
|      * filter input elements, and submit a new search. | ||||
|      */ | ||||
|     $('div.filters form button[type="reset"]').click(function() { | ||||
|         var form = $(this).parents('form'); | ||||
|         form.find('div.filter').each(function() { | ||||
|             $(this).find('div.value input').val(''); | ||||
|         }); | ||||
|         form.submit(); | ||||
|         return false; | ||||
|     }); | ||||
| 
 | ||||
|     $('div.grid-wrapper').on('click', 'div.grid th.sortable a', function() { | ||||
|         var th = $(this).parent(); | ||||
|         var wrapper = th.parents('div.grid-wrapper'); | ||||
|         var grid = wrapper.find('div.grid'); | ||||
|         var data = { | ||||
|             sort: th.attr('field'), | ||||
|             dir: (th.hasClass('sorted') && th.hasClass('asc')) ? 'desc' : 'asc', | ||||
|             page: 1, | ||||
|             partial: true | ||||
|         }; | ||||
|         wrapper.mask("Loading..."); | ||||
|         $.get(grid.attr('url'), data, function(data) { | ||||
|             wrapper.unmask(); | ||||
|             grid.replaceWith(data); | ||||
|         }); | ||||
|         return false; | ||||
|     }); | ||||
| 
 | ||||
|     $('#body').on('mouseenter', 'div.grid.hoverable table tbody tr', function() { | ||||
|         $(this).addClass('hovering'); | ||||
|     }); | ||||
| 
 | ||||
|     $('#body').on('mouseleave', 'div.grid.hoverable table tbody tr', function() { | ||||
|         $(this).removeClass('hovering'); | ||||
|     }); | ||||
| 
 | ||||
|     $('div.grid-wrapper').on('click', 'div.grid table tbody td.view', function() { | ||||
|         var url = $(this).attr('url'); | ||||
|         if (url) { | ||||
|             location.href = url; | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     $('div.grid-wrapper').on('click', 'div.grid table tbody td.edit', function() { | ||||
|         var url = $(this).attr('url'); | ||||
|         if (url) { | ||||
|             location.href = url; | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     $('div.grid-wrapper').on('click', 'div.grid table tbody td.delete', function() { | ||||
|         var url = $(this).attr('url'); | ||||
|         if (url) { | ||||
|             if (confirm("Do you really wish to delete this object?")) { | ||||
|                 location.href = url; | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     $('div.grid-wrapper').on('change', 'div.grid div.pager select#grid-page-count', function() { | ||||
|         var select = $(this); | ||||
|         var wrapper = select.parents('div.grid-wrapper'); | ||||
|         var grid = wrapper.find('div.grid'); | ||||
|         var data = { | ||||
|             per_page: select.val(), | ||||
|             partial: true | ||||
|         }; | ||||
|         wrapper.mask("Loading..."); | ||||
|         $.get(grid.attr('url'), data, function(data) { | ||||
|             wrapper.unmask(); | ||||
|             grid.replaceWith(data); | ||||
|         }); | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
|     /* | ||||
|      * Add "check all" functionality to tables with checkboxes. | ||||
|      */ | ||||
|     $('body').on('click', 'div.grid table thead th.checkbox input[type="checkbox"]', function() { | ||||
|         var table = $(this).parents('table:first'); | ||||
|         var checked = $(this).prop('checked'); | ||||
|         table.find('tbody tr').each(function() { | ||||
|             $(this).find('td.checkbox input[type="checkbox"]').prop('checked', checked); | ||||
|         }); | ||||
|     }); | ||||
|      | ||||
|     $('body').on('click', 'div.dialog button.close', function() { | ||||
|         var dialog = $(this).parents('div.dialog:first'); | ||||
|         dialog.dialog('close'); | ||||
|     }); | ||||
| 
 | ||||
| }); | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar