JS Tricky request for confirmation

Evo jedne temice za ljubitelje frontenda i javascripta. Također i za hejtere, koji će i ovdje sigurno pronaći svoju poslasticu…

Trebalo mi je barem jedno 5 godina da mi se iskristalizira jedno rješenje u glavi i baš me razveselilo kada me maloprije opalila ideja iz “vedra neba” :D. Nije baš iz vedra neba, jer sam se svih proteklih godina mic po mic približavao rješenju…ali sada je sve sjelo fino na mjesto.

Znači još davno sam htio napraviti opciju da mogu korisnika priuptati dialogom, na način:

“Jeste li sigurni da želite nastaviti?”

…i onda o njegovoj odluci nastaviti izvršavati code od linije gdje sam ga to pitao.

Naravno, sirovi stari-prastari JS nam to omogućava na način:

function submit(someData){
	if(!confirm("Jeste li sigurni da želite nastaviti ? ") return;
	console.log("Korisnik je nastavio...")
}

Znači, jedna linija koda, koristeći naredbu confirm, nam omogućava tu opciju.
Jedino je mali problemčić što nemamo nikakvu mogućnost utjecaja na izgled tog confirmation dialoga.

I sada sam ja htio napraviti isto to, ali sa svojim custom dialogom. Ali isto da bude jedna linija koda.

Naravno, sve može biti jedna linija koda, ako code nakucamo u jednoj linji…zato kada kažem jedna linija coda, onda mislim na liniju ekvivalent ovoj
if(!confirm("Jeste li sigurni da želite nastaviti ? ") return;
…za koju u potpunosti nema smisla da se razbija na više linija.

Uglavnom, nisam imao blage ideje da je moguće tako nešto izvesti sa custom codom i custom dialogom…pa sam pitao po forumu. Tamo su me također savjetovali da se to ne može izvesti…i preporučavali mi da na dialog zakačim callback koji će korisnika preusmjeriti na željenu daljnju akciju ako klikne potvrdni button.

E sad, tako sa callbackom sam radio davno prije nego sam tražio elegantnije rješenje…i tad sam baš htio da stvar radi po principu metode confirm. Da ne moramo ama baš ništa drugo petljati sa code-om, osim da zakačimo custom komadić codea na liniju gdje radimo konfirmaciju. Činilo se i meni to poprilično nemogućim, ali sam trazio neko rješenje…i izbasao sam na neko poluelegantno rješenje koje je bilo skoro one-line…

…s vremenom sam to uspio još malo uljepšati…i danas sam dobio perfect varijantu. Znači doslovice mogu napisati jednako “mesa”, kao u varijanti sa native confirm metodom, znači code mi izgleda ovako:

function submit(someData){
	if(!custom_confirm("Jeste li sigurni da želite nastaviti ?") return;
	console.log("Korisnik je nastavio...")
}

custom_confirm mogu nazvati kako želim, ta funkcija očito postoji negdje u pozadini i pravo pitanje je što se krije unutra, hehe
Oke, u mojoj varijanti ipak ima malo više mesa, što namjerno ovdje nisam prikazao. Ali ne puno, sakrio sam ni manje ni više nego ravno 9 karaktera koji upadaju u istu liniju sa konfirmacijom …koji će također ostati tajna… čisto da vam zadatak izgleda jednako težak koliko je meni izgledao prije 5 godina…kad sam mislio da je to nemoguće izvesti :smiley:
P.S. Nema nikakvih JS kompajlera koji od tog codea stvaraju nekakav prošireni code :wink:

E sad, ako ovdje ima ljubitelja i znalaca JS-a, mislim da imamo dobru temu. Zanima me jel može netko skužiti, ili barem naslutiti kako sam ovo izveo? :smiley:

P.S. Da bi imali mogućnost prikazivanja dialoga konfirmacije, logično je da imamo nekakvu custom funkciju tipa dialog, koja se poziva očito unutar custom_confirm-a. Ta dialog funkcija nudi opciju poziva tipa:

dialog({
	text:confirmation_text, 
	onTrue:positive_callback, 
	onFalse:negative_callback 
});

Znači za raspetljavanja custom_confirma je logično da imamo dialog na raspolaganju, njega za potrebe odgonetavanja problema ne moramo konstrurirati. Pravo pitanje je na koji način je custom_confirm upregnuo taj dialog, da se dobije željeno ponašanje konfirmacije.

Ako netko voli mozgati, bit će mi drago davati sugestije :wink:

žž.

Da hoćeš poslušati da uzmeš dokumentaciju i čitaš/učiš redom, završio bi to za par mjeseci najviše. U zavisnosti gdje se pogodi sekcija u dokumentaciji koja ti treba.
Ovo sve što ti pišem vrijedi ako čitaš dokumentaciju od “korica do korica”.

Evo za manje od 10 sekundi dva linka koji mi rade tu stvar.

http://bootstrap-confirmation.js.org/#examples

<button class="btn btn-default" data-toggle="confirmation">Confirmation</button>

http://bootboxjs.com/examples.html

bootbox.confirm("This is the default confirm!", function(result){ 
    console.log('This was logged in the callback: ' + result); 
});

Fundation, Materials, Bulma i ostale nisam ni tražio.

Ili ne čitaš ili ne razumiješ. Lijepo sam napisao u tekstu da ne dolazi u obzir opcija sa callbackom, a ti staviš upravo to:

bootbox.confirm("This is the default confirm!", function(result){ 
    // ** Ovo ovdje ti je callback koji je pozvan od strane bootbox.confirm**
});

Znači, kod mene nema callbacka:

function submit(someData){
	if(!custom_confirm("Jeste li sigurni da želite nastaviti ?") return;
	console.log("Korisnik je nastavio...")
}

Nego custom_confirm stavljaš točno na onu liniju gdje želiš stopirati code koji se izvršava, i koji će se nastaviti izvršavati nakon što korisnik prihvati konfirmaciju.

P.S. naravno, nisam ni ja 5 godina drilao samo po tom problemu xd. Nisam uopće drilao po tome…samo kako bi me zadesio bljesak inspiracije, tako sam ponekada updejtao svoju varijantu. I sada je baš sjelo na svoje mjesto. A ako misliš da je jednostavno dobiti code koji sam na kraju dobio…izvoli…probaj :slight_smile: Ovo tvoje ne ispunjava zahtjev! :wink:

Da ponovim zahtjev:

ZAHTJEV: Da se ponaša identično kao nativni confirm, s aspekta ugradnje code-a …ali da se može upregnuti custom dialog umjesto nativnog conifrm dialoga.

Ili da objasnim zahjev na primjeru:
Imaš neku funkciju u skripti koja izgleda ovako:

(Znači sljedeća funkcij ima razno raznog mesa…to je samo simbolički prikaz da je tu puno svega…)

function someFunkcion(x,y,z, ...n){

	var nesto1 = nekaAkcija1(x,y);
	var nesto2 = nekaAkcija2(x,y);
	var nesto3 = nekaAkcija3(x,y);
	var nesto4 = nekaAkcija4(x,y);
	var nesto5 = nekaAkcija5(x,y);
	var nesto6 = nekaAkcija6(x,y);
	var nesto7 = nekaAkcija7(x,y);

	//..itd 
}

I sada poželiš ubaciti konfirmaciju prije nego se izvršava akcija: “nekaAkcija5”, bogme najjednostavniji način ubacivanja konfirmacije je sljedeće:

function someFunkcion(x,y,z, ...n){

	var nesto1 = nekaAkcija1(x,y);
	var nesto2 = nekaAkcija2(x,y);
	var nesto3 = nekaAkcija3(x,y);
	var nesto4 = nekaAkcija4(x,y);

	if(!confirm("Sigurno želiš nastaviti?"))return;

	var nesto5 = nekaAkcija5(x,y);
	var nesto6 = nekaAkcija6(x,y);
	var nesto7 = nekaAkcija7(x,y);

	//..itd
}

…znači bez ikakvog preslagivanja ostatka funkcije u nekakav callback parametar, želimo funkciju presjeći sa confirm metodom. Eto, to je zahtjev. :wink:

U’ sunce ti poljubim. :rofl:

Dok se sjetim svega…
swal je vrlo korišten.
Osmi primjer.

Ne kužim opasku, u tom osmom primjeru se također koristi callback da se korisnika preusmjeri na tu callback akciju nakon što potvrdi konfirmaciju.

Tim pristupom ne možeš ugraditi konfirmaciju kao što sam naveo u svom zadnjem gore postu.

Ne kažem ja sada da je to nešto strašno loše…nije. Ali da ga hebeš, ne može biti elegantnije nego da presječeš neku funkciju gdje god i da tamo injektaš mali code konfirmacije. Bez potrebe da ostatak funkcije kopiraš u callback parametar itd.

A možeš imati varijantu da nekada i želiš raditi konfirmaciju, a nekada ne želiš. Onda u toj varijanti sa callback-om moraš dodatno petljati da posložiš code kada imaš takav slučaj…

…kako god, radio sam i ja tako nekada. Ali ovo je sigurno bolje.
Ali tema i nije o tome da ustvrđujemo koje je bolje…nego, dali netko naslućuje kako se može to izvesti na način kako sam to izveo. :slight_smile:

Zašto ne bi moglo?

const custom_confirm = (obj) => {
  Swal.fire({
    title: 'Are you sure?',//obj.title
    text: "You won't be able to revert this!",// obj.text
    type: 'warning',// obj.type
    showCancelButton: true,// obj.showCancelButton
    confirmButtonColor: '#3085d6',// obj.confirmButtonColor
    cancelButtonColor: '#d33',// obj.cancelButtonColor
    confirmButtonText: 'Yes, delete it!'// obj.confirmButtonText
  }).then((result) => {
    if (result.value) {
      Swal.fire(
        'Deleted!',
        'Your file has been deleted.',
        'success'
      )
    }
  });
};

// anywhere in code
custom_confirm(obj);

Pa neće taj tvoj “anywhere in code” stopirati da se izvrši code koji se nalazi nakon toga. Bila potvrdna konfirmacija ili nebila…

Pa vrati mu false na kraju (u zavisnosti od ispunjenja uslova).
Pogledaj u dokumentaciji koje sve event-e podržava.

A zašto bi ostatak code-a čekao korisnika dok on odabere Aprove ili Cancel?
Ostatak ide dalje…a po user odabiru se trigira callback koji je zakačen na taj odabir. Ili je to tu nekako drugačije rješeno?

Sad kad se sjetim da je @belmin pisao o mogućnostima da se asinkronim djelovima codea zada da se ponašaju sinkrono i da ih ostatak codea čeka…bogme ovo možda i ima šanse da tako funkcionira. Al zasad nisam dobio dojam da se o tome radi.
Mada je to možda još jedna opcija da se rješi zahtjev iz uvoda. Da li bi moglo i tako…tesko mi reći, nisam se još igrao sa time da asinkrone dijelove setupiram da budu sinkroni.

Zbog toga što ti je takva postavka zadatka? :grinning:

function submit(someData) {
  if (!custom_confirm(obj)) {
     return;
  }
  console.log("Korisnik je nastavio...")
}

Ako si ovo u pravu da swal tako radi…opet ostaje jednako visiti u zraku što se to nalazi untar Swal.fire da omogući takvo ponašanje da izvršavanje code-a čeka dok user ne izvrši akciju aprove ili cancel.

Bum probao baš…iskreno sumnjam da tako radi. Barem ne vidim razlog zašto si ti odjednom zaključio da tako radi. :confused:

Može se čuditi 5 godina (očekujući kvazi-providjenje) a sa druge strane može se pročitati i kod. Pa šta bude brže.

if (!custom_confirm(obj)) {
  return;
}

Blok ovaj ovde očekuje vrijednost koju može interpretirati k’o boolean.
Tvoje je da mu to omogućiš u custom_confirm funkciji - no matter what, it should return bool.

Koliko ja mogu da vidim Swal.fire vraca Promise tako da se nista ne ceka, tj. main thread nije blokiran.

Na approve se poziva Promise.resolve, a na cancel vjerovatno Promise.reject i onda ti u then/catch callbacku mozes raditi dalje sta zelis.

Simple, a blocking kod u bilo kom pogledu je losa ideja :slight_smile:

Ako ti nije problem, jel bi mogao istipkati komad code-a koji bi zahtjevao user reakciju, a koji bi blokirao main thread, stavio ga da čeka dok user ne odreagira?

Naravno, ako je to neki simple kratak code…nemoj se dat tlačit :smiley: :smiley:

Ja, kao što rekoh…nisam radio još sa tim varijantama čekanja/nečekanja. Znam samo da asinkrono ide ajax request, image loadinzi, setTimout …i takve forice. Ali nemam na pameti kako bi mogao definirati da takvi pozivi budu sinkroni, tj. da ostatk code-a čeka da se izvrše.
Sjećam se da si jednom negdje spomenuo da se i to može…tad sam prvi puta čuo da i to postoji, hehe.

A unutar ove teme mi palo na pamet da bi i sa takvom opcijom možda mogao rješiti custom_confirm, da se čeka njegovo resolvanje.

Pa s obzirom da si iz prve debelo promašio poantu, nemam vremena proučavati tvoje prijedloge dok mi ne ostaviš dojam da si na tragu…

…ako želiš elaborirati svoje rješenje, samo daj. Neću ti ga ja elaborirati. :wink:

Generalno da, ali da se user pričeka da nešto aprova ili odbije, ne vidim neki problem?

Pa i nativni confirm() je blocking code i neće se ništa izvršavati dok se ne zatvori. Isto kao i svaki nativni alert.
Mislim stvarno da za konfirmaciju odluke, blokiranje codea ne može unesti nikakvu štetu.

:upside_down_face:
Znači nisi ni prob’o kod?

Ništa onda, sačekaćemo sljedećih 5 godina. :blush:

Neću reći da nisi u pravu, ali nisam iskreno ništa probavao. Di bi došao da idem za svakim po forumima i analziram što je on negdje testirao i klikao…i koje file-ove moram downloadati da bi to isto testirao.
Ako si već imao funkcionalan primjer, mogao si mi linkat radnu verziju u nekakav jsFiddle file i probao bi.

Onaj primjer 8 što se da kliknuti na swal stranici (što si linkao), ništa ne dokazuje! :wink: