1 /**
  2  * Sourcemap.Object: Representation of Sourcemap data.
  3  * @fileoverview  Sourcemap.Editor: Main component to handle saving and calculating the object values of Sourcemaps.
  4  * @version 0.8
  5  * @author sourcemap@media.mit.edu
  6  * @package sourcemap
  7  * @subpackage js
  8  */
  9 
 10 
 11 if ( typeof(Sourcemap) == "undefined" ) { Sourcemap = {}; }
 12 
 13 
 14 /** 
 15 * @namespace Sourcemap object
 16 * @constructor 
 17 */
 18 Sourcemap.Object = function(obj) {
 19 	jQuery.extend(this, obj);
 20 	/**
 21 	 * @param val, this is the value of parameter to set the value
 22 	 */
 23 	this.setName = function(val) {
 24 		this.name = Sourcemap.Util.utf8encode(val);
 25 	};
 26 	this.setDescription = function(val) {
 27 	    this.description = Sourcemap.Util.utf8encode(val);	   
 28 	/**
 29 	 *Trigger objectDescriptionUpdated in Editor.js 
 30 	 */	
 31 	    $("body").trigger("objectDescriptionUpdated", [val]);							
 32 	};
 33 	this.setImageLink = function(val) {
 34 		this.imagelink = Sourcemap.Util.utf8encode(val);
 35 	};
 36 	this.setPermissions = function(val) {};
 37 	this.setOrigin = function(val) {
 38 		// TODO Object Depency on Smap existing
 39 		SMap.geoCoder.getLocations(val, function(response){
 40 				if(response.Status.code != 200) { 
 41 					$("body").trigger("originGeoError", ["object"]);
 42 					SMap.removeOrigin(); 
 43 				} 
 44 				else {
 45 					if(typeof(response.Placemark[0]) != 'undefined') {
 46 						place = response.Placemark[0];		
 47 					    point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
 48 
 49 						if(point != null && (point.lat() != 0 && point.lng() != 0) && response.Status.code == 200){						
 50 							$("body").trigger("originGeoMessage", ["object", place.address]);	
 51 							var adjPoint = point.lat() + "|" + point.lng();
 52 							objectConfig.latlon = adjPoint;			
 53 						
 54 					       	SMap.setOrigin(val, objectConfig.parts); SMap.refreshMap(); //TODO objconfig dep
 55 							objectConfig.origin = Sourcemap.Util.utf8encode(place.address); // TODO 
 56 						}
 57 						else { 
 58 							$("body").trigger("originGeoError", ["object"]); 
 59 							SMap.removeOrigin(); 
 60 						}
 61 					}
 62 				}
 63 				//TODO look at this
 64 				for (var i=0;i<objectConfig.parts.length;i++) {
 65 					objectConfig.setPartOrigin(i, objectConfig.parts[i].origin, false);
 66 				}
 67 			});
 68 	};
 69 	this.setDestination = function(val) {}; // TODO Remove?
 70 	this.setVia = function(val) {}; // TODO Remove?	
 71 	this.setWeight = function(val) { this.weight = val; };
 72 	this.setShipping = function(val) { this.shipping = val; };
 73 	this.setEmissions = function(val) { this.emissions = val; };
 74   	this.setEmbodiedEmissions = function(val) { this.embodied = val; };
 75   	this.setTransportEmissions = function(val) { this.transport = val; };
 76 	this.setUPC = function(val) { this.upc = val; };
 77 
 78         this.setProcessEmissions = function(val) {this.processEmissions =val;};
 79         this.setEndoflifeEmissions = function(val) {this.endoflifeEmissions =val;};
 80 
 81 	/**
 82 	 * //===== Object Functions =====\\	
 83 	 * call objects controller to save the part, process, endoflife
 84 	 */
 85 	this.save = function() {
 86 	        var saveData = "data="+Sourcemap.Util.utf8encode(JSON.stringify(objectConfig));
 87 		$("body").trigger("savingObject", [objectConfig]); 
 88 	
 89 		$.post(Sourcemap.siteurl+"objects/save",  saveData, this.saveConfirmation);
 90 	};
 91 
 92        /**
 93 	* check the parts flag, if it is "remove" then
 94 	* set the parts value as null
 95 	*/
 96 	this.saveConfirmation = function(data) {
 97 		for ( var i = 0; i < objectConfig.parts.length; i++ ) {
 98 			if( typeof(objectConfig.parts[i]) != 'undefined') {
 99 				if(objectConfig.parts[i].flag == "remove") {
100 					objectConfig.parts[i] = null;
101 				} else {
102 					objectConfig.parts[i].flag = "unchanged";
103 				}
104 			}
105 		}
106 		Sourcemap.pageTracker._trackEvent("SMap", "Save", "Sourcemap "+objectConfig.type+"-"+objectConfig.oid+" saved");				
107 		$("body").trigger("saveObjectConfirmation", [data]); 
108 	};
109 	
110         /**
111 	 * 	//===== Part Functions =====\\	
112 	 * add a new part and set all the values
113 	 * @param part name, description, emissions, linkid
114 	 * trigger partAdded in Editor.js
115 	 */
116 
117 	this.addPart = function(name, description, emissions, linkid) {
118 		// TODO partstub and partlocationstub depend		
119 		var id = this.partcount;
120 
121 		var part = new Object();
122 		part.name = name != '' ? name : Sourcemap.Template.partstubname;
123 	  	part.description = typeof(description) != 'undefined' ? description : '';
124 	  	part.linkid = typeof(linkid) != 'undefined' ? linkid : 0;
125 	  	part.rawemissions = typeof(emissions) != 'undefined' ? Number(emissions) : 0;
126 	  	part.emissions = 0;
127 
128 		part.flag = 'add';	
129 		part.imid = -1;
130 		part.weight = 0;
131 		part.shipping = 0;
132 		part.latlon = '0|0';	
133 		part.via = 'Part Via';
134 		part.transportemissions = 0;
135 		part.origin = Sourcemap.Template.partlocationstubname;
136     
137 		this.parts[id] = part;
138 		this.partcount = this.partcount+1;
139 		Sourcemap.pageTracker._trackEvent("SMap", "AddedPart", "Added "+part.name+" to "+objectConfig.oid+"");				
140 		
141 	       /**
142 		* Trigger partAdded in Editor.js
143 		*/
144 		$("body").trigger("partAdded", [id, part.name, part.description, part.emissions, part.linkid]); 		
145 	};
146 
147         /**
148 	 * remove a part, remove the visualization, set the flag to remove
149 	 * @param id, this is the part id to be removed
150 	 * @see  #recalculateObjectValues
151 	 */
152 	this.removePart = function(id) {
153 		if(this.parts[id].flag == "add") {
154 			this.parts[id].flag = "unchanged";
155 		}
156 		else { this.parts[id].flag = "remove";}
157 
158 		this.recalculateObjectValues();
159 		
160 	     /**
161 	      * Trigger partRemoved in Editor.js
162 	      */
163 		$("body").trigger("partRemoved", [id]); 			
164 	};
165 
166         /**
167 	 * calculate totalemissions, transportEmissions, embodiedEmissions,
168 	 * endoflifeEmissions, processEmissions and set their values
169 	 * @see  #setEmissions
170 	 * @see  #setEmbodiedEmissions
171 	 * @see  #setTransportEmissions
172 	 * @see  #setShipping
173 	 * @see  #setWeight
174 	 * @see  #setProcessEmissions
175 	 * @see  #setEndoflifeEmissions
176 	 */
177 
178 	this.recalculateObjectValues = function() {
179 		var emissionsTotal = 0;
180 		var shippingDistanceTotal = 0;
181 	        var weightTotal = 0;
182 		var transportEmissionsTotal = 0;
183 		var transportKGKM = 0;
184 		var embodiedEmissionsTotal = 0;
185 	        var processEmissionsTotal = 0;
186 	        var endoflifeEmissionsTotal = 0;
187 
188  		for ( var i = 0; i < this.parts.length; i++ ) {
189  			var part = this.parts[i];
190  			if(part.flag != "remove") {
191  			    embodiedEmissionsTotal += parseFloat(part.emissions);
192  			    transportEmissionsTotal += (parseFloat(part.shipping) * parseFloat(part.weight/1000) * parseFloat(part.transportemissions));
193  			    weightTotal += parseFloat(part.weight);
194 
195 
196 			    if(typeof(this.parts[i].process) != 'undefined') {
197 				
198  				if(part.flag == "changed"){
199 					for(var q=0; q<part.process.length; q++) {
200                    			       var process = part.process[q];
201 					       if(process.flag == false){
202 						   if(process.unit != "kg"){
203 						       processEmissionsTotal += (parseFloat(process.emissions) * parseFloat(process.factor));             
204 						       
205 						   } else{
206  						       processEmissionsTotal += (parseFloat(process.emissions) * weightTotal);             
207  						   }
208 					       }  
209 					       
210 					   }
211 				    }
212 				}
213 
214 			    if(typeof(this.parts[i].endoflife) != 'undefined') {
215 				
216 				if(part.flag == "changed") {
217 				    for(var p=0; p<part.endoflife.length; p++) {
218 					var endoflife = part.endoflife[p];
219 					if(endoflife.flag == false) {
220 					    if (endoflife.type == "reuse") {
221 						endoflifeEmissionsTotal += -((parseFloat(embodiedEmissionsTotal)) + (parseFloat(processEmissionsTotal)));
222 						
223 					    } else {
224 						
225 						endoflifeEmissionsTotal += (parseFloat(endoflife.emissions) * weightTotal);
226 					    }
227 					}
228 				    }
229 				}
230 			    }
231  			    
232 			    
233  			    shippingDistanceTotal += parseFloat(part.shipping);					
234  			    transportKGKM += (Number(part.weight) * Number(part.shipping));
235  			}	
236  		}
237 	    if(this.showembodied == "on") { emissionsTotal += embodiedEmissionsTotal;}		
238 	    if(this.showtransport == "on") { emissionsTotal += transportEmissionsTotal;}
239 	    if(this.showuse == "on" && this.usageemissions != null) { 
240 		emissionsTotal += parseFloat(this.usageemissions);
241 		}
242 	    if(this.showprocess == "on") { emissionsTotal += processEmissionsTotal;}
243             if(this.showendoflife == "on") {emissionsTotal += endoflifeEmissionsTotal; }
244 	    
245 	    this.setEmissions(emissionsTotal);
246 	    this.setEmbodiedEmissions(embodiedEmissionsTotal);
247 	    this.setTransportEmissions(transportEmissionsTotal);
248 	    this.setShipping(shippingDistanceTotal);
249 	    this.setWeight(weightTotal);
250 	    this.setProcessEmissions(processEmissionsTotal);
251             this.setEndoflifeEmissions(endoflifeEmissionsTotal);
252 	    
253 	    /**
254 	     * Trigger objectTotalsCalculated in Editor.js
255 	     */
256 	    $("body").trigger("objectTotalsCalculated", [emissionsTotal, embodiedEmissionsTotal, transportEmissionsTotal, shippingDistanceTotal, weightTotal, processEmissionsTotal, endoflifeEmissionsTotal]);
257 	};
258 	
259 
260     /**
261      * //========Endoflife Setting Functions=====\\
262      * @param partId, endoflfe_id, flag
263      * @see  #recalculateObjectValues
264      */
265     this.removeEndoflife = function(partId, endoflife_id, flag){
266         this.parts[partId].endoflife[endoflife_id].flag = flag;
267 	this.recalculateObjectValues();
268  
269 	/**
270 	 * Trigger endoflifeRemoved in editor.js
271 	 */
272 	$("body").trigger("endoflifeRemoved", [partId, endoflife_id]); 			
273 	
274     };
275 
276 	    
277     /**
278      * Add a new endoflife
279      * @param partId. endoflife_id, endofife_type, emissions, unit, flag
280      * @see  #recalculateObjectValues
281      */
282     this.addEndoflife = function(partId, endoflife_id, endoflife_type, emissions, unit, flag) {
283 	
284 	if(typeof(this.parts[partId].endoflife) == 'undefined') {
285 	    this.parts[partId].endoflife = Array();
286 	    
287 	}
288 	var endoflife = new Object();
289 	endoflife.type = endoflife_type;
290 	endoflife.emissions = emissions;
291 	endoflife.unit = unit;
292 	endoflife.flag = flag;
293 	this.parts[partId].endoflife[endoflife_id] = endoflife;
294 
295 	if(this.parts[partId].flag != "add") {
296 	    this.parts[partId].flag = "changed";  
297 	}
298 
299 	this.recalculateObjectValues();
300 
301 	/**
302 	 * trigger endoflifeAdded in Editor.js
303  	 */
304 	
305 	$("body").trigger("endoflifeAdded", [partId, endoflife_id, endoflife_type, emissions, unit]);
306     };
307 
308 
309     /**
310      * Add the endoflife type if there ia a change in type
311      * @param PartId, endoflife_id, type
312      * @see  #recalculateObjectValues
313      */
314 
315     this.setEndoflifeType = function(partId, endoflife_id, type) {
316 	this.parts[partId].endoflife[endoflife_id].type = type;
317 	if(this.parts[partId].flag != "add") {
318 	    this.parts[partId].flag = "changed";  
319 	}
320 	
321 	this.recalculateObjectValues();
322 
323 	/**
324 	 * trigger endoflifeType in Editor.js 
325 	 */
326 	$("body").trigger("endoflifeType", [partId, endoflife_id, type]);
327     };
328 
329     /**
330      * Add the endoflife emissions if there is a change in emissions
331      * @param partId, endoflife_id, emissions
332      * @see  #recalculateObjectValues
333      */
334 
335     this.addEndoflifeEmissions = function(partId, endoflife_id, emissions) {
336 	
337 	 this.parts[partId].endoflife[endoflife_id].emissions = emissions;
338 	 
339 	 if(this.parts[partId].flag != "add") {
340 	 this.parts[partId].flag = "changed";  
341 	 }
342 	 
343 	 this.recalculateObjectValues();
344 	
345 	/**
346 	 * Trigger endoflifeEmissions in Editor.js 
347 	 */
348 	 $("body").trigger("endoflifeEmissions", [partId, endoflife_id, emissions]);  
349     };
350     
351     
352 
353        /**
354 	*  //========Process setting functions=====\\
355 	*  Remove a process
356 	*  @param part_id, process_id, flag
357 	*  @see  #recalculateObjectValues
358 	*/
359 
360         this.removeProcess = function(part_id, process_id, flag) {
361 	    this.parts[part_id].process[process_id].flag = flag;
362 	    this.recalculateObjectValues();
363 	   
364 	    /**
365 	     *  trigger processRemoved in Editor.js 
366 	     */
367 	    $("body").trigger("processRemoved", [part_id, process_id]); 			
368 	};
369     
370        
371         /**
372 	 * Add a new process 
373 	 * @param part_id, process_id, process_name, emissions, unit, flag, factor, check
374 	 * @see  #recalculateObjectValues
375 	 */
376        this. addProcess = function (part_id, process_id, process_name, emissions, unit, flag, factor, check){
377 	   if(typeof(this.parts[part_id].process) == 'undefined') {
378 	       this.parts[part_id].process = Array();
379 	       
380 	   }
381 
382 	   var process = new Object();
383 	   process.name = process_name;
384            process.emissions = emissions;
385 	   process.unit = unit;
386 	   process.flag = flag;
387 	   process.factor = factor;
388 	   process.label = 0;
389 	   
390 	   this.parts[part_id].process[process_id] = process;
391 	   this.recalculateObjectValues();
392 
393            /**
394 	    * Trigger processAdded in Editor.js 
395 	    */
396 	   $("body").trigger("processAdded", [part_id, process_id, process.name, process.emissions, process.unit, process.flag, process.factor, check]);
397        };
398 	   
399     
400         /**
401 	 * Set the process name if there is a change in the name
402 	 * @param part_id, process_id, process_name
403 	 */
404         this.setProcessName = function(part_id, process_id, process_name){
405 
406 	    this.parts[part_id].process[process_id].name = process_name;
407 	    this.parts[part_id].process[process_id].flag = 0;
408 	   	    
409 	    if(this.parts[part_id].flag != "add") {
410 		this.parts[part_id].flag = "changed";  
411 	    }
412 	   
413 	    /**
414 	     * Trigger addingProcessName in Editor.js
415 	     */
416 	    $("body").trigger("addingProcessName", [process_id, process_name]);
417         };
418 
419      
420         /**
421 	 * Set the process emissions if there is a change in the emissions
422 	 * @param part_id, process_id, emissions
423 	 * @see  #recaiculateObjectValues
424 	 */
425          this.addProcessEmissions = function(part_id, process_id, emissions){
426 		   
427              this.parts[part_id].process[process_id].emissions = emissions;		 
428 	     this.parts[part_id].process[process_id].label = 1;
429 	     this.parts[part_id].process[process_id].flag = 0;
430 	     if(this.parts[part_id].flag != "add") {
431 	     this.parts[part_id].flag = "changed";
432 	     }
433 	     this.recalculateObjectValues(); 
434 	    
435 	     /**
436 	      * Trigger addingProcessEmissions in Editor.js
437 	      */
438 	     $("body").trigger("addingProcessEmissions", [process_id, emissions]);
439 	     
440 	 };
441     
442         /**
443 	 * Set the process unit if there is a change in the unit
444 	 * @param part_id, process_id, unit
445 	 * @see  #recalculateObjectValues
446 	 */
447          this.setProcessUnit = function (part_id, process_id, unit) {
448 	     this.parts[part_id].process[process_id].unit = unit;
449 	     if(this.parts[part_id].flag != "add") {
450 		 this.parts[part_id].flag = "changed";  
451 	     }
452 	     
453 	     this.recalculateObjectValues();
454 
455 	     /**
456 	      * trigger addingProcessUnit in Editor.js
457 	      */
458 	     $("body").trigger("addingProcessUnit", [process_id, unit]);
459 	 };
460 
461 
462         /**
463 	 * Set the process factor if there is a change in the factor
464 	 * @param part_id, process_id, factor, check
465 	 * @see  #recalculateObjectVaiues
466 	 */
467          this.setProcessFactor = function(part_id, process_id, factor, check){
468 	    this.parts[part_id].process[process_id].factor = factor;
469 	    this.parts[part_id].process[process_id].label = 1;
470 	    this.parts[part_id].process[process_id].flag = 0;
471 	    if(this.parts[part_id].flag != "add") {
472 	    this.parts[part_id].flag = "changed";
473 	    }
474 	
475 	    this.recalculateObjectValues(); 
476 	     
477 	     /**
478 	      * Trigger addingProcessFactor in Editor.js 
479 	      */
480 	    $("body").trigger("addingProcessFactor", [process_id, factor, check]);
481 	  
482         };
483     
484 
485     /**
486      *  //===== Part Settor Functions =====\\
487      *  Set part name if there is a change in the part name
488      * @param id, name, this is the part id and the name 
489      */
490     
491     this.setPartName = function(id, name) {	
492 	name = name.replace(/[']/g,'');	
493 	this.parts[id].name = name; 
494 	if(this.parts[id].flag != "add") {
495 		this.parts[id].flag = "changed";  
496 	    }
497 	
498 	/**
499 	 * Trigger partNameUpdated	  
500 	 */
501 	$("body").trigger("partNameUpdated", [id, name]);					
502     };
503 
504     /**
505      * Set part description to new description
506      * @param id. description. This is the part_id, description
507      */
508 	this.setPartDescription = function(id, description) {
509 			description = description.replace(/[']/g,'');
510 			this.parts[id].description = description; 				
511 			if(this.parts[id].flag != "add") {
512 				this.parts[id].flag = "changed";  
513 			}
514 
515 	                /**
516 			 * Trigger partDescriptionUpdated in Editor.js 
517 			 */
518 			$("body").trigger("partDescriptionUpdated", [id, description]);
519 	};
520 
521 
522     /**
523      * Set part weight to the new value
524      * @param id, weight. This is the part id, new(entered) weight
525      * @see  #recalculateObjectValues
526      */
527 	this.setPartWeight = function(id, weight) {
528 		// TODO partkgfactor should e tied to something
529 		if(typeof(parseFloat(weight)) != "number") { weight = 0; }
530 		this.parts[id].weight = Number(weight*Sourcemap.Template.partkgfactor);				
531 		if(this.parts[id].flag != "add") {
532 			this.parts[id].flag = "changed";  
533 		}
534 
535 		this.setPartEmissions(id, weight * this.parts[id].rawemissions, true);
536 		this.setPartTransportEmissions(id, $("#"+id+ " .input-via").val(), true); // TODO Strange Depend.	
537 
538 		this.recalculateObjectValues(); $("body").trigger("partTotalsChanged", [id]); 
539 
540 	        /**
541 		 * Trigger partWeightUpdated in Editor.js
542 		 */
543 		$("body").trigger("partWeightUpdated", [id, weight]);
544 		
545 	};
546 
547     /**
548      * Set the new part shipping
549      * @param id, shipping. This is the part id and shipping
550      * @see  #recalculateObjectValues
551      */
552 	this.setPartShipping = function(id, shipping) {
553 		// TODO partkgfactor should e tied to something
554 		this.parts[id].shipping = Number(shipping);		
555 				
556 		if(this.parts[id].flag != "add") {
557 			this.parts[id].flag = "changed";  
558 		}
559 
560 		this.recalculateObjectValues(); 
561  
562 	        /**
563 		 * Trigger partTotalsChanged, partShippingUpdated in Editor.js
564 		 */    
565 	        $("body").trigger("partTotalsChanged", [id]); 		
566 		$("body").trigger("partShippingUpdated", [id, shipping]);				
567 	};
568 
569      /**
570       * Set set new part emissions
571       * @param id, emissions, supress
572       */
573 	
574 	this.setPartEmissions = function(id, emissions, suppress) {		
575 		this.parts[id].emissions = emissions; 
576 		if(this.parts[id].flag != "add") {
577 			this.parts[id].flag = "changed";  
578 		}
579 
580 		if(!(suppress)) { this.recalculateObjectValues(); $("body").trigger("partTotalsChanged", [id]); }
581            
582 	       /**
583 		* trigger partEmissionsUpdated
584 		*/
585 		$("body").trigger("partEmissionsUpdated", [id, emissions]);
586 	};
587 
588 
589       /**
590        * Set the part rawEmissions
591        * @param id, rawemissions, supress
592        */
593 	this.setPartRawEmissions = function(id, rawemissions, suppress) {	
594 		this.parts[id].rawemissions = rawemissions; 
595 		if(this.parts[id].flag != "add") {
596 			this.parts[id].flag = "changed";  
597 		}
598 
599 		this.setPartEmissions(id, rawemissions * this.parts[id].weight, true);
600 
601 		if(!(suppress)) { this.recalculateObjectValues(); $("body").trigger("partTotalsChanged", [id]); }
602 
603 	       /**
604 		* Trigger partEmissionsUpdated in Editor.js
605 		*/
606 		$("body").trigger("partRawEmissionsUpdated", [id, rawemissions]);
607 	};
608 
609        /**
610 	* Set the paet transport emissions
611 	* @param id, transportemissions, supress
612 	*/
613 	this.setPartTransportEmissions = function(id, transportemissions, suppress) {
614 		this.parts[id].transportemissions = transportemissions; 
615 		if(this.parts[id].flag != "add") {
616 			this.parts[id].flag = "changed";  
617 		}
618 
619 		if(!(suppress)) { this.recalculateObjectValues(); $("body").trigger("partTotalsChanged", [id]); }
620 
621 	       /**
622 		* Trigger partTransportEmissionsUpdated in Editor.js
623 		*/ 
624 		$("body").trigger("partTransportEmissionsUpdated", [id, transportemissions]);
625 	};
626 
627        /**
628 	* Set the new part type
629 	* @param id, via, type
630 	* @see  #recalculateObjectValues
631 	* @see  setPartTransportEmissions
632 	*/
633 	this.setPartVia = function(id, via, type) {
634 		this.parts[id].via = type;				
635 		if(this.parts[id].flag != "add") {
636 			this.parts[id].flag = "changed";  
637 		}
638 
639 		this.setPartTransportEmissions(id, $("#"+id+ " .input-via").val(), true);		
640 		this.recalculateObjectValues(); $("body").trigger("partTotalsChanged", [id]); 
641 
642 
643 	       /**
644 		* Trigger partViaUpdated in Editor.js
645 		*/
646 		$("body").trigger("partViaUpdated", [id, via]);
647 	};
648 
649        /**
650 	* Set the new part origin
651 	* @param id, origin, geofeedback
652 	*/
653 	this.setPartOrigin = function(id, origin, geofeedback) {
654 		// Todo has objectConfig Depend. Callback should be seperated out
655 		objectOrigin = GLatLng.fromUrlValue(this.latlon.replace(/[|]/g,','));
656 		SMap.geoCoder.getLocations(Sourcemap.Util.utf8decode(origin), function(response){
657 
658 			if(response.Status.code != 200) { if(geofeedback) { 
659 				$("body").trigger("originGeoError", [id]);
660 				SMap.removePart(objectConfig.parts[id], id); 
661 			} }
662 
663 		    point = new GLatLng(response.Placemark[0].Point.coordinates[1], response.Placemark[0].Point.coordinates[0]);	
664 			place = response.Placemark[0];		
665 			
666 			if(point != null && (point.lat() != 0 && point.lng() != 0) && response.Status.code == 200){
667 				if(geofeedback) { $("body").trigger("originGeoMessage", [id, place.address]); }
668 				newDistance = Sourcemap.Util.getDistance(objectOrigin, point);
669 				if(objectConfig.parts[id].flag != "add") {
670 					objectConfig.parts[id].flag = "changed";  
671 				}
672 				objectConfig.parts[id].latlon = point.lat() + "|" + point.lng();	
673 				objectConfig.parts[id].origin = Sourcemap.Util.utf8encode(place.address);							
674 				objectConfig.setPartShipping(id, newDistance);				
675 				objectConfig.setPartTransportEmissions(id, $("#"+id+ " .input-via").val(), false);		
676 				// TODO needed? this.recalculateObjectValues()
677 				
678 			        /**
679 				 * Trigger partOriginUpdated in Editor.js
680 				 */
681 				$("body").trigger("partOriginUpdated", [id, place.address]);	
682 			}
683 			else { if(geofeedback) { 
684 				   
685 				/**
686 				 * Tirgger originGeoError in Editor.js
687 				 */
688 				$("body").trigger("originGeoError", [id]);
689 				SMap.removePart(objectConfig.parts[id], id); 
690 			} }
691 		});
692 	};
693 
694 	//===== Sample Debug Bindings =====\\
695 	$("body").bind("originGeoMessage", function(e, id, msg) { 
696 		Sourcemap.debug("Event::originGeoMessage {"+id+":"+msg+"}");
697 	});	
698 	$("body").bind("originGeoError", function(e, id) {
699 		Sourcemap.debug("Event::originGeoError:"+id);
700 	});
701 	$("body").bind("partAdded", function(e, id, name, desc, emiss, link) { 
702 		Sourcemap.debug("Event::partAdded {"+name+","+id+","+desc+","+emiss+","+link+"}");
703 	});
704 	$("body").bind("savingObject", function(e, obj) {
705 		Sourcemap.debug("Event::savingObject {"); Sourcemap.debug(obj); Sourcemap.debug("}");
706 	});	
707 	$("body").bind("saveObjectConfirmation", function(e, data) { 
708 		Sourcemap.debug("Event::saveObjectConfirmation {"+data+"}");
709 	});
710 	$("body").bind("objectTotalsCalculated", function(e, emis, embod, trans, ship, weight) {
711 		Sourcemap.debug("Event::objectTotalsCalculated {"+emis+","+embod+","+trans+","+ship+","+weight+"}");
712 	});
713 	
714 };
715 
716