// 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 cookieConsentBox(redirectUrl:String, ?message:String, ?phoneRequired = false) { js.Browser.console.log("cookieConsentBox should load modal..."); var m = App.j("#myModal"); m.find(".modal-title").html("Consentement RGPD"); m.find(".modal-dialog").removeClass("modal-lg"); untyped m.modal(); ReactDOM.render(jsx('<$CookieConsentBox 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 { 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); }); } } }