You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							262 lines
						
					
					
						
							7.7 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							262 lines
						
					
					
						
							7.7 KiB
						
					
					
				| //React lib | |
| import react.ReactMacro.jsx; | |
| import react.ReactDOM; | |
| import react.*; | |
| import react.router.*; | |
| //custom components | |
| import react.order.*; | |
| import react.product.*; | |
| import react.store.*; | |
| import react.map.*; | |
| import react.user.*; | |
| 
 | |
| //require bootstrap JS since it's bundled with browserify | |
| //@:jsRequire('bootstrap') extern class Bootstrap{} | |
| //@:jsRequire('jquery') extern class JQ extends js.jquery.JQuery{} | |
| 
 | |
| class App { | |
| 
 | |
| 	public static var instance : App; | |
| 	public var LANG : String; | |
| 	public var currency : String; //currency symbol like € or $ | |
| 	public var t : sugoi.i18n.GetText;//gettext translator | |
| 
 | |
| 	//i dont want to use redux now... saved state from react.OrderBox | |
| 	public static var SAVED_ORDER_STATE : Dynamic; | |
| 
 | |
| 	function new(?lang="fr",?currency="€") { | |
| 		//singleton | |
| 		instance = this; | |
| 		if(lang!=null) this.LANG = lang; | |
| 		this.currency = currency; | |
| 	} | |
| 
 | |
| 	/** | |
| 	 * Returns a jquery object like $() in javascript | |
| 	 * @deprecated | |
| 	 */ | |
| 	public static inline function j(r:Dynamic):js.JQuery { | |
| 		return new js.JQuery(r); | |
| 	} | |
| 
 | |
| 	public static inline function jq(r:Dynamic):js.jquery.JQuery{ | |
| 		return new js.jquery.JQuery(r); | |
| 	} | |
| 
 | |
| 	/** | |
| 	 * The JS App will be available as "_" in the document. | |
| 	 */ | |
| 	public static function main() { | |
| 		 | |
| 		//untyped js.Browser.window.$ = js.Lib.require("jQuery"); | |
| 		untyped js.Browser.window._ = new App(); | |
| 	} | |
| 
 | |
| 	public function getCart() { | |
| 		return new ShopCart(); | |
| 	} | |
| 
 | |
| 	public function getTagger(cid:Int ) { | |
| 		return new Tagger(cid); | |
| 	} | |
| 
 | |
| 	public function getTuto(name:String, step:Int) { | |
| 		new Tuto(name,step); | |
| 	} | |
| 	 | |
| 	/** | |
| 	 * remove method for IE compat | |
| 	 */ | |
| 	public function remove(el:js.html.Element){ | |
| 		if (el == null) return; | |
| 		el.parentElement.removeChild(el); | |
| 	} | |
| 	 | |
| 	public function getVATBox(ttcprice:Float,currency:String,rates:String,vat:Float,formName:String){ | |
| 		 | |
| 		var input = js.Browser.document.querySelector('form input[name="${formName}_price"]'); | |
| 		 | |
| 		remove( js.Browser.document.querySelector('form input[name="${formName}_vat"]').parentElement.parentElement ); | |
| 		 | |
| 		ReactDOM.render(jsx('<$VATBox ttc="$ttcprice" currency="$currency" vatRates="$rates" vat="$vat" formName="$formName"/>'),  input.parentElement); | |
| 		 | |
| 		//remove(input); | |
| 		 | |
| 	} | |
| 
 | |
| 	/*public function getProductComposer(){ | |
| 		//js.Browser.document.addEventListener("DOMContentLoaded", function(event) { | |
| 			//ReactDOM.render(jsx('<$ComposerApp/>'), js.Browser.document.getElementById("app")); | |
| 		//}); | |
| 	}*/ | |
| 
 | |
| 	/** | |
| 	 * Removes the form element and replace it by a react js component | |
| 	 * @param	divId | |
| 	 * @param	productName | |
| 	 * @param	txpProductId | |
| 	 * @param	formName | |
| 	 */ | |
| 	public function getProductInput(divId:String, productName:String, txpProductId:String, formName:String ){ | |
| 
 | |
| 		js.Browser.document.addEventListener("DOMContentLoaded", function(event) { | |
| 
 | |
| 			//dirty stuff to remove "real" input, and replace it by the react one | |
| 			App.j("form input[name='"+formName+"_name']").parent().parent().remove(); | |
| 			App.j("form select[name='" + formName+"_txpProductId']").parent().parent().remove(); | |
| 
 | |
| 			if (txpProductId == null) txpProductId = ""; | |
| 
 | |
| 			ReactDOM.render(jsx('<$ProductInput productName="$productName" txpProductId="$txpProductId" formName="$formName"/>'),  js.Browser.document.getElementById(divId)); | |
| 		}); | |
| 	} | |
| 
 | |
| 	public function initReportHeader(){ | |
| 		ReactDOM.render(jsx('<$ReportHeader />'),  js.Browser.document.querySelector('div.reportHeaderContainer')); | |
| 	} | |
| 	 | |
| 	public function initOrderBox(userId:Int, distributionId:Int, contractId:Int, contractType:Int, date:String, place:String, userName:String, currency:String, hasPayments:Bool,callbackUrl:String){ | |
| 
 | |
| 		untyped App.j("#myModal").modal(); | |
| 		var onValidate = function() js.Browser.location.href = callbackUrl; | |
| 		var node = js.Browser.document.querySelector('#myModal .modal-body'); | |
| 		ReactDOM.unmountComponentAtNode(node); //the previous modal DOM element is still there, so we need to destroy it | |
| 		ReactDOM.render(jsx('<$OrderBox userId="$userId" distributionId="$distributionId"  | |
| 			contractId="$contractId" contractType="$contractType" date="$date" place="$place" userName="$userName"  | |
| 			onValidate=$onValidate currency=$currency hasPayments=$hasPayments />'),node,postReact); | |
| 
 | |
| 	} | |
| 
 | |
| 	function postReact(){ | |
| 		trace("post react"); | |
| 		haxe.Timer.delay(function(){ | |
| 			untyped jq('[data-toggle="tooltip"]').tooltip(); | |
| 			untyped jq('[data-toggle="popover"]').popover(); | |
| 		},500); | |
| 		 | |
| 	} | |
| 
 | |
| 	public static function roundTo(n:Float, r:Int):Float { | |
| 		return Math.round(n * Math.pow(10,r)) / Math.pow(10,r) ; | |
| 	} | |
| 
 | |
| 
 | |
| 	/** | |
| 	 * Ajax loads a page and display it in a modal window | |
| 	 * @param	url | |
| 	 * @param	title | |
| 	 */ | |
| 	public function overlay(url:String,?title,?large=true) { | |
| 
 | |
| 		if (title != null) title = StringTools.urlDecode(title); | |
| 
 | |
| 		var r = new haxe.Http(url); | |
| 		r.onData = function(data) { | |
| 
 | |
| 			//setup body and title | |
| 			var m = App.j("#myModal"); | |
| 			m.find(".modal-body").html(data); | |
| 			if (title != null) m.find(".modal-title").html(title); | |
| 
 | |
| 			if (!large) m.find(".modal-dialog").removeClass("modal-lg"); | |
| 
 | |
| 
 | |
| 			untyped App.j('#myModal').modal(); //bootstrap 3 modal window | |
| 
 | |
| 		} | |
| 		r.request(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	 * Displays a login box | |
| 	 */ | |
| 	public function loginBox(redirectUrl:String,?message:String,?phoneRequired=false) { | |
| 		var m = App.j("#myModal"); | |
| 		m.find(".modal-title").html("S'identifier"); | |
| 		m.find(".modal-dialog").removeClass("modal-lg"); | |
| 		untyped m.modal(); | |
| 		ReactDOM.render(jsx('<$LoginBox redirectUrl="$redirectUrl" message=$message phoneRequired="$phoneRequired"/>'),  js.Browser.document.querySelector('#myModal .modal-body')); | |
| 		return false; | |
| 	} | |
| 
 | |
| 	/** | |
| 	 *  Displays a sign up box | |
| 	 */ | |
| 	public function registerBox(redirectUrl:String,?message:String,?phoneRequired=false) { | |
| 		var m = App.j("#myModal"); | |
| 		m.find(".modal-title").html("S'inscrire"); | |
| 		m.find(".modal-dialog").removeClass("modal-lg"); | |
| 		untyped m.modal(); | |
| 		ReactDOM.render(jsx('<$RegisterBox redirectUrl="$redirectUrl" message=$message phoneRequired="$phoneRequired"/>'),  js.Browser.document.querySelector('#myModal .modal-body')); | |
| 		return false; | |
| 	} | |
| 
 | |
| 	public function shop(place:Int, date:String) { | |
| 		ReactDOM.render(jsx('<$Store date=$date place=$place/>'),  js.Browser.document.querySelector('#shop')); | |
| 	} | |
| 	 | |
| 	public function groupMap(lat:String,lng:String,address:String) { | |
| 		ReactDOM.render(jsx('<$GroupMapRoot lat="$lat" lng="$lng" address="$address"/>'),  js.Browser.document.querySelector('#map')); | |
| 	} | |
| 
 | |
| 	/** | |
| 	 * Helper to get values of a bunch of checked checkboxes | |
| 	 * @param	formSelector | |
| 	 */ | |
| 	public function getCheckboxesId(formSelector:String):Array<String>{ | |
| 		var out = []; | |
| 		var checkboxes = js.Browser.document.querySelectorAll(formSelector + " input[type=checkbox]"); | |
| 		for ( input in checkboxes ){ | |
| 			var input : js.html.InputElement = cast input; | |
| 			if ( input.checked ) out.push(input.value); | |
| 		} | |
| 		return out; | |
| 	} | |
| 
 | |
| 
 | |
| 	#if plugins | |
| 	public function getHostedPlugin(){ | |
| 		return new hosted.js.App(); | |
| 	} | |
| 	#end | |
| 
 | |
| 	/** | |
| 	 * set up a warning message when leaving the page | |
| 	 */ | |
| 	public function setWarningOnUnload(active:Bool, ?msg:String){ | |
| 		if (active){ | |
| 			js.Browser.window.addEventListener("beforeunload", warn); | |
| 		}else{ | |
| 			js.Browser.window.removeEventListener("beforeunload", warn); | |
| 		} | |
| 
 | |
| 	} | |
| 
 | |
| 	function warn(e:js.html.Event) { | |
| 		var msg = "Voulez vous vraiment quitter cette page ?"; | |
| 		//js.Browser.window.confirm(msg); | |
| 		untyped e.returnValue = msg; //Gecko + IE | |
| 		e.preventDefault(); | |
| 		return msg; //Gecko + Webkit, Safari, Chrome etc. | |
| 	} | |
| 
 | |
| 	/** | |
| 	 * Anti Doubleclick with btn elements. | |
| 	 * Can be bypassed by adding a .btn-noAntiDoubleClick class | |
| 	 */ | |
| 	public function antiDoubleClick(){ | |
| 
 | |
| 		for( n in js.Browser.document.querySelectorAll(".btn:not(.btn-noAntiDoubleClick)") ){ | |
| 			n.addEventListener("click",function(e:js.html.MouseEvent){ | |
| 				var x = untyped e.target; | |
| 				x.classList.add("disabled"); | |
| 				haxe.Timer.delay(function(){ | |
| 					x.classList.remove("disabled"); | |
| 				},1000); | |
| 			}); | |
| 		} | |
| 		 | |
| 	} | |
| } | |
| 
 | |
| 
 |