1 /*-------------------------------------------------------------------------------
  2  * Xataface Web Application Framework
  3  * Copyright (C) 2005-2009 Web Lite Solutions Corp (shannah@sfu.ca)
  4  * 
  5  * This program is free software; you can redistribute it and/or
  6  * modify it under the terms of the GNU General Public License
  7  * as published by the Free Software Foundation; either version 2
  8  * of the License, or (at your option) any later version.
  9  * 
 10  * This program is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  * GNU General Public License for more details.
 14  * 
 15  * You should have received a copy of the GNU General Public License
 16  * along with this program; if not, write to the Free Software
 17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 18  *-------------------------------------------------------------------------------
 19  */
 20 /**
 21  * This jquery plugin allows you to convert any HTML element or field into
 22  * a record browser.  Clicking the browser button will open a modal dialog
 23  * that allows the user to search and browse through a number of records
 24  * in a table.
 25  *
 26  * Example usage: 
 27  *
 28  * <a href="#" id="selector">Click me to find stuff</a>
 29  * ...
 30  *
 31  * $('#selector').RecordBrowser({
 32  *		table: 'people',
 33  *		filters: {
 34  *			group_id: 10
 35  *		},
 36  *		callback: function(values){
 37  *			// values is an object with the records that the user 
 38  *			// selected
 39  *			for ( var id in values ){
 40  *				// id is the id of the record
 41  *				// values[id] is the title of the record
 42  *			}
 43  *		}
 44  *	});
 45  *
 46  * Alternatively you could use the RecordBrowserWidget function to convert a text field
 47  * into a RecordBrowser:
 48  *
 49  * <input type="text" id="textfield"/>
 50  * ...
 51  * $('#textfield').RecordBrowserWidget({
 52  *		table: 'people',
 53  *		filters: {
 54  *			group_id: 10
 55  *		},
 56  *		callback: function(values){
 57  *			// values is an object with the records that the user 
 58  *			// selected
 59  *			for ( var id in values ){
 60  *				// id is the id of the record
 61  *				// values[id] is the title of the record
 62  *			}
 63  *		}
 64  *	});
 65  * 
 66  */
 67 (function ($){
 68 	var xataface = {};
 69 	xataface.RecordBrowser = function(o){
 70 		/**
 71 		 * The name of the table to browse for records in.
 72 		 * @var string
 73 		 */
 74 		this.table = null;
 75 		
 76 		/**
 77 		 * The name of the column to use as the value in the option list.
 78 		 * Set this value to __id__ to use the record id.
 79 		 * If this value is blank, then the primary key is used so long as
 80 		 * the primary key only has a single column.  If it is a compound
 81 		 * primary key, then the record id is used by default.
 82 		 * @var string
 83 		 */
 84 		this.value = null;
 85 		
 86 		/**
 87 		 * The name of the column to use as the title in the option list.
 88 		 * Set this value to __title__ to use the record title ( or leave blank).
 89 		 *
 90 		 * @var string
 91 		 */
 92 		this.text = null;
 93 		
 94 		/**
 95 		 * Search filters to add to the query.
 96 		 * @var object
 97 		 */
 98 		this.filters = {};
 99 		
100 		/**
101 		 * Callback function to be called with the selected values.
102 		 * function(values){}
103 		 * @var function
104 		 */
105 		this.callback = null;
106 		
107 		/**
108 		 * The document element that is used to display the dialog.
109 		 * @var HTMLDOMElement
110 		 */
111 		this.el = document.createElement('div');
112 		
113 		/**
114 		 * The base url to the RecordBrowser directory.
115 		 * @var string
116 		 */
117 		this.baseURL = DATAFACE_URL+'/js/RecordBrowser';
118 		
119 		for ( var i in o ){
120 			this[i] = o[i];
121 		}
122 		
123 		/**
124 		 * A flag to indicate whether the record select list
125 		 * needs to be updated when updateRecords() is called.
126 		 * The list would need to be updated if the filter parameters change.
127 		 * @var boolean
128 		 */
129 		this.dirty = true;
130 		$('head').append('<link rel="stylesheet" type="text/css" href="'+DATAFACE_URL+'/css/smoothness/jquery-ui-1.7.2.custom.css"/>');
131 		
132 		
133 		
134 		
135 	}
136 	
137 	xataface.RecordBrowser.prototype = {
138 		display : function(){
139 			var rb = this;
140 			$('body').append(this.el);
141 			$(this.el).load(this.baseURL+'/templates/RecordBrowser.html', function(){
142 				var dialog = this;
143 				var searchChangeHandler = function(){
144 					rb.filterRecords({
145 						'-search' : $(this).val()
146 					});
147 				};
148 				$(this).find('.xf-RecordBrowser-search-field')
149 					.keyup(searchChangeHandler)
150 					.change(searchChangeHandler);
151 					//.blur(searchChangeHandler);
152 				//$(this).find('.xf-RecordBrowser-select').css('height', '90%');
153 				$(this).find('.xf-RecordBrowser-select-field')
154 					.css('width', '100%')
155 					.attr('size', 8);
156 					
157 				$(this).find('.xf-RecordBrowser-addnew-button').RecordDialog({
158 					table: rb.table,
159 					callback: function(){
160 						rb.dirty=true;
161 						rb.updateRecords();
162 					}
163 				});
164 				
165 				$(this).dialog({
166 					'title': 'Select Record',
167 					'buttons' : {
168 						'Select' : function(){
169 							var out = {};
170 							$(dialog).find('.xf-RecordBrowser-select-field :selected').each(function(i, selected){
171 								out[$(selected).attr('value')] = $(selected).text();
172 							});
173 								
174 							if ( rb.callback ) rb.callback(out);
175 							$(this).dialog("close");
176 						
177 						},
178 						'Cancel' : function(){
179 							$(this).dialog("close");
180 						
181 						}
182 						
183 					},
184 					'modal' : true,
185 					'resize': function(event, ui){
186 						$(dialog).find('.xf-RecordBrowser-select-field').css('height', ($(dialog).height()-60)+'px');
187 						
188 					}
189 				});
190 				
191 				rb.updateRecords();
192 			});
193 		},
194 		
195 		filterRecords : function(filter){
196 			
197 			for ( var i in filter ){
198 				if ( this.filters[i] != filter[i] ) this.dirty = true;
199 				this.filters[i] = filter[i];
200 			}
201 			this.updateRecords();
202 		},
203 		
204 		updateRecords : function(){
205 			
206 			if ( this.dirty ){
207 				var sel = $(this.el).find('.xf-RecordBrowser-select-field');
208 				var val = $(sel).val();
209 				//var el = $(this.el);
210 				sel.load(this.getDataURL(), function(){
211 					sel.val(val);
212 				});
213 				this.dirty = false;
214 			}
215 		},
216 		
217 		getDataURL : function(){
218 			var url = DATAFACE_SITE_HREF+'?-action=RecordBrowser_data&-table='+encodeURIComponent(this.table);
219 			if ( this.value ) url += '&-value='+encodeURIComponent(this.value);
220 			if ( this.text ) url += '&-text='+encodeURIComponent(this.text);
221 			for ( var i in this.filters ){
222 				url += '&'+encodeURIComponent(i)+'='+encodeURIComponent(this.filters[i]);
223 			}
224 			return url;
225 		}
226 	
227 	};
228 	
229 	$.fn.RecordBrowser = function(options){
230 		
231 		return this.each(function(){
232 			var obj = $(this);
233 			obj.click(function(){
234 				if ( typeof(options.click) == 'function' ){
235 					options.click();
236 				}
237 				var rb = new xataface.RecordBrowser(options);
238 				rb.display();
239 			});
240 		});
241 	};
242 	
243 	$.fn.RecordBrowserWidget = function(options){
244 		return this.each(function(){
245 			
246 			var obj = $(this);
247 			if ( obj.hasClass("xf-RecordBrowserWidget") ){
248 				// This field is already a record browser with different
249 				// settings.  We need to change it.  So we remove the old
250 				// display field.
251 				var oldDisplayField = obj.next();
252 				var oldButton = oldDisplayField.next();
253 				oldDisplayField.remove();
254 				oldButton.remove();
255 				
256 				obj.removeClass('xf-RecordBrowserWidget');
257 			}
258 			
259 			
260 			var displayField = document.createElement('input');
261 			$(displayField).attr('type','text')
262 				.addClass('xf-RecordBrowserWidget-displayField')
263 				//.css('width', obj.width()+'px')
264 				//.css('height', obj.height()+'px')
265 				.css('cursor', 'pointer')
266 				//.css('border', '1px solid black')
267 				.attr('readonly', 1);
268 			
269 
270 			$(displayField).insertAfter(this);
271 			
272 			obj.css('display','none')
273 				.addClass('xf-RecordBrowserWidget');
274 			
275 			if ( !options.frozen ){
276 				obj.change(function(){
277 					var id;
278 					if ( options.value && options.value != '__id__' ){
279 						id = encodeURIComponent(options.value)+'='+encodeURIComponent(obj.val());
280 					} else {
281 						id = obj.val();
282 					}
283 					var url = DATAFACE_SITE_HREF+'?-action=RecordBrowser_lookup_single&-table='+options.table+'&-id='+encodeURIComponent(id);
284 					if ( options.text ) url += '&-text='+encodeURIComponent(options.text);
285 					$.get(url, function(text){
286 						
287 						$(displayField).val(text);
288 					});
289 				});
290 				var a = document.createElement('a');
291 				$(a).addClass('xf-RecordBrowser-button')
292 					.css('cursor', 'pointer')
293 					.html('<img src="'+DATAFACE_URL+'/images/search_icon.gif" border="0" /><span class="xf-RecordBrowser-button-label"> Lookup</span>');
294 				$(a).find('.xf-RecordBrowser-button-label')
295 					.css('display', 'none');
296 				
297 				$(a).insertAfter(displayField);
298 				if ( !options.callback ){
299 					options.callback = function(vals){
300 						for ( var i in vals ){
301 							//$(displayField).val(vals[i]);
302 							obj.val(i);
303 							obj.trigger('change');
304 						}
305 					};
306 				}
307 				$(a).RecordBrowser(options);
308 				$(displayField).RecordBrowser(options);
309 			} else {
310 				//alert(obj.val());
311 			}
312 			
313 			if ( obj.val() ){
314 				var id;
315 				if ( options.value && options.value != '__id__' ){
316 					id = encodeURIComponent(options.value)+'='+encodeURIComponent(obj.val());
317 				} else {
318 					id = obj.val();
319 				}
320 				var url = DATAFACE_SITE_HREF+'?-action=RecordBrowser_lookup_single&-table='+options.table+'&-id='+encodeURIComponent(id);
321 				if ( options.text ) url += '&-text='+encodeURIComponent(options.text);
322 				$.get(url, function(text){
323 					//alert(text);
324 					$(displayField).val(text);
325 				});
326 			}
327 			
328 			
329 		});
330 	};
331 })(jQuery);