Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Modal - example javascript toggle #683

Labels

Comments

@ghost
Copy link

ghost commented Apr 18, 2017

It's about docs -> http://bulma.io/documentation/components/modal/
I think that it should contain example javascript toggle.

@AntonyGarand
Copy link

Bulma does not include any JavaScript interaction. You will have to implement the class toggle yourself

As bulma does not include js, I believe adding javascript code to the docs would be more confusing than helping.

@ghost
Copy link
Author

ghost commented Apr 19, 2017

I think that it is already confusing when framework calls itself "without javascript" but includes elements that won't work without it!

@AntonyGarand
Copy link

It does work without javascript, but it is static: You can add the is-active class at load time and the modal window will indeed work.

@airblade
Copy link

It's easy enough to toggle the is-active class on the modal div.

But – and I only found this out after reading the source of the JavaScript bundle on the docs site – you also need to toggle the is-clipped class on the <html> element to stop the page underneath scrolling when you try to scroll in the modal.

It would be great to add that to the docs.

@hroman-codes
Copy link

hroman-codes commented Apr 27, 2017

@airblade Do you mind providing a code sample? I am actually trying to accomplish the same thing you and others are explaining. Having a little trouble.

@airblade
Copy link

@iamromanh Assuming you have a link which opens your modal, e.g.:

<a id="open-modal" href="">Open modal</a>

This ES5 JavaScript (or similar, I just typed it out without testing) should open it:

document.querySelector('a#open-modal').addEventListener('click', function(event) {
  event.preventDefault();
  var modal = document.querySelector('.modal');  // assuming you have only 1
  var html = document.querySelector('html');
  modal.classList.add('is-active');
  html.classList.add('is-clipped');

  modal.querySelector('.modal-background').addEventListener('click', function(e) {
    e.preventDefault();
    modal.classList.remove('is-active');
    html.classList.remove('is-clipped');
  });
});

@nqthqn
Copy link

nqthqn commented May 5, 2017

I really appreciate the design decision to keep this a javascript-free framework.

Here's how you might toggle classes in Elm,

In the View...

navToggler : Bool -> Html Msg
navToggler activeMenu =
    span
        [ class <| "nav-toggle" ++ (isActive activeMenu), onClick MainMenuToggle ]
        [ span [] []
        , span [] []
        , span [] []
        ]

isActive : Bool -> String
isActive active =
    if active then
        " is-active"
    else
        ""

And then in the Update...

MainMenuToggle ->
    ( { model | isMenuActive = not model.isMenuActive }, Cmd.none )

@raman162
Copy link

raman162 commented Aug 21, 2017

My Implmentation using html5 data-attributes and jquery.

Html

<a class="open-modal" data-modal-id="#my-modal">Open My Modal</a>

<div aria-hidden="" class="modal" id="my-modal">
  <div class="modal-background close-modal" data-modal-id="#my-modal"></div>
  <div class="modal-content">

   </div>
   <button aria-label="close" class="delete close-modal" data-modal-id="#my-modal"></button>
</div>

Javascript

function toggleModalClasses(event) {
    var modalId = event.currentTarget.dataset.modalId;
    var modal = $(modalId);
    modal.toggleClass('is-active');
    $('html').toggleClass('is-clipped');
  };

$('.open-modal').click(toggleModalClasses);

$('.close-modal').click(toggleModalClasses);

@aligoren
Copy link

Hi there. If you need some help with javascript events, I created a basic class. Maybe this will help you.

For example HTML code;

<div class="modal" id="myModal">
  <div class="modal-background"></div>
  <div class="modal-card">
    <header class="modal-card-head">
      <p class="modal-card-title">Modal title</p>
      <button class="delete" aria-label="close" data-bulma-modal="close"></button>
    </header>
    <section class="modal-card-body">
      <p>There is something here</p>
    </section>
    <footer class="modal-card-foot">
      <button class="button is-success">Save changes</button>
      <button class="button" data-bulma-modal="close">Cancel</button>
    </footer>
  </div>
</div>

<button id="btn">Click for Modal</button>

For Example JS Code;

class BulmaModal {
	constructor(selector) {
		this.elem = document.querySelector(selector)
		this.close_data()
	}
	
	show() {
		this.elem.classList.toggle('is-active')
		this.on_show()
	}
	
	close() {
		this.elem.classList.toggle('is-active')
		this.on_close()
	}
	
	close_data() {
		var modalClose = this.elem.querySelectorAll("[data-bulma-modal='close'], .modal-background")
		var that = this
		modalClose.forEach(function(e) {
			e.addEventListener("click", function() {
				
				that.elem.classList.toggle('is-active')

				var event = new Event('modal:close')

				that.elem.dispatchEvent(event);
			})
		})
	}
	
	on_show() {
		var event = new Event('modal:show')
	
		this.elem.dispatchEvent(event);
	}
	
	on_close() {
		var event = new Event('modal:close')
	
		this.elem.dispatchEvent(event);
	}
	
	addEventListener(event, callback) {
		this.elem.addEventListener(event, callback)
	}
}

var btn = document.querySelector("#btn")
var mdl = new BulmaModal("#myModal")

btn.addEventListener("click", function () {
	mdl.show()
})

mdl.addEventListener('modal:show', function() {
	console.log("opened")
})

mdl.addEventListener("modal:close", function() {
	console.log("closed")
})

@Ickorus
Copy link

Ickorus commented Nov 12, 2018

Also, In looking for the same thing you were. I found this:
bulma-modal-with-javascript ( searched google)

@jeturcotte
Copy link

re: @aligoren ... nice! and on my birthday, too. A great present =)

@Nomkid
Copy link

Nomkid commented Oct 22, 2020

The navbar page in the documentation has a JavaScript example, why can't this? I don't want to spend my time learning JavaScript (I already know how, but as an example) just to get a modal working! What if I'm just building a simple single-page blog, and don't know any JS?

@jgthms jgthms added the pinned label Oct 22, 2020
@IlanVivanco
Copy link

Based on @aligoren's script I changed it to automount every modal instance.

index.html

<button class="modal-button" data-toggle="modal" data-target="#video">Open modal</button>

<div class="modal" id="video">
  <div class="modal-background"></div>
  <div class="modal-content">
    Lorem ipsum dolor sit amet
  </div>
  <button class="modal-close is-large" aria-label="close"></button>
</div>

BulmaModal.js

class BulmaModal {
  constructor(modalButton) {
    const target = modalButton.dataset.target;
    
    if (target) {
      this.button = modalButton;
      this.modal = document.querySelector(target);
      this.html = document.querySelector("html");
      
      this.openEvent();
      this.closeEvents();
    }
  }
  
  show() {
    this.modal.classList.toggle("is-active");
    this.html.classList.add("is-clipped");
    
    this.onShow();
  }
  
  close() {
    this.modal.classList.toggle("is-active");
    this.html.classList.toggle("is-clipped");
    
    this.onClose();
  }
  
  openEvent() {
    this.button.addEventListener("click", (e) => {
      e.preventDefault();
      this.show();
    });
  }
  
  closeEvents() {
    const closeElements = this.modal.querySelectorAll(".modal-background, .modal-close");
    
    closeElements.forEach((element) => {
      element.addEventListener("click", (e) => {
        e.preventDefault();
        this.close();
      });
    });
  }
  
  onShow() {
    const event = new Event("modal:show");
    this.modal.dispatchEvent(event);
  }
  
  onClose() {
    const event = new Event("modal:close");
    this.modal.dispatchEvent(event);
  }
}

export default BulmaModal;

main.js

import BulmaModal from 'BulmaModal.js'

const modals = document.querySelectorAll("[data-toggle='modal']");
modals.forEach((modal) => new BulmaModal(modal));

If needed you can add event too:
main.js

document.querySelector(".modal").addEventListener("modal:show", (event) =>{ console.log(event) });

@aligoren
Copy link

aligoren commented Apr 5, 2021

Based on @aligoren's script I changed it to automount every modal instance.

index.html

<button class="modal-button" data-toggle="modal" data-target="#video">Open modal</button>

<div class="modal" id="video">
  <div class="modal-background"></div>
  <div class="modal-content">
    Lorem ipsum dolor sit amet
  </div>
  <button class="modal-close is-large" aria-label="close"></button>
</div>

BulmaModal.js

class BulmaModal {
  constructor(modalButton) {
    const target = modalButton.dataset.target;
    
    if (target) {
      this.button = modalButton;
      this.modal = document.querySelector(target);
      this.html = document.querySelector("html");
      
      this.openEvent();
      this.closeEvents();
    }
  }
  
  show() {
    this.modal.classList.toggle("is-active");
    this.html.classList.add("is-clipped");
    
    this.onShow();
  }
  
  close() {
    this.modal.classList.toggle("is-active");
    this.html.classList.toggle("is-clipped");
    
    this.onClose();
  }
  
  openEvent() {
    this.button.addEventListener("click", (e) => {
      e.preventDefault();
      this.show();
    });
  }
  
  closeEvents() {
    const closeElements = this.modal.querySelectorAll(".modal-background, .modal-close");
    
    closeElements.forEach((element) => {
      element.addEventListener("click", (e) => {
        e.preventDefault();
        this.close();
      });
    });
  }
  
  onShow() {
    const event = new Event("modal:show");
    this.modal.dispatchEvent(event);
  }
  
  onClose() {
    const event = new Event("modal:close");
    this.modal.dispatchEvent(event);
  }
}

export default BulmaModal;

main.js

import BulmaModal from 'BulmaModal.js'

const modals = document.querySelectorAll("[data-toggle='modal']");
modals.forEach((modal) => new BulmaModal(modal));

If needed you can add event too:
main.js

document.querySelector(".modal").addEventListener("modal:show", (event) =>{ console.log(event) });

Almos 3 years ago, I wrote this simple script. It still works and you made it amazing. Thanks <3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment