I need to fix a few things here:
The delete button does not work after the drop event. The delete only works on items not in the dropzone. Not sure what is wrong here.
also, it would be better to add the delete button to each dropped item instead of cloning it.
I need to be able sort the dropped items.
sortable is not included in the current demo below.
HTML:
<div id="items">
<div class="item"><span>Item 111111</span>
<span class="delete"><button>Delete Line</button></span>
</div>
<div class="item"><span>Item 222222</span>
<span class="delete"><button>Delete Line</button></span>
</div>
<div class="item"><span>Item 333333</span>
<span class="delete"><button>Delete Line</button></span>
</div>
</div>
<div style="" id="cart">
<div class="info">Drag Items Here</div>
</div>
<div class=""><span>test delete works here but not after a drag event</span>
<span class="delete"><button>Delete Line</button></span>
</div>
Here is the DomReady event:
$$('.item').addEvent('mousedown', function (event) {
event.stop();
// `this` refers to the element with the .item class
var item = this;
var clone = item.clone().setStyles(item.getCoordinates()).setStyles({
opacity: 0.7,
position: 'absolute'
}).inject(document.body);
var drag = new Drag.Move(clone, {
droppables: $('cart'),
onDrop: function (dragging, cart) {
dragging.destroy();
item.removeClass('item');
item.addClass('item_dz');
if (cart != null) {
item.clone().inject(cart);
cart.highlight('#4679BD', '#FFF');
item.removeClass('item_dz');
item.addClass('item');
}
},
onEnter: function (dragging, cart) {
cart.tween('background-color', '#FFF04F');
},
onLeave: function (dragging, cart) {
cart.tween('background-color', '#FFF');
},
onCancel: function (dragging) {
dragging.destroy();
}
});
drag.start(event);
});
$$('.delete').addEvents({
click: function () {
this.getParent().destroy();
this.destroy();
},
mouseover: function () {
this.tween('opacity', '1');
this.getPrevious(['.item_dz']).fade(0.3);
this.getPrevious(['.item_dz']).tween('background-color', '#fff', '#f00');
},
mouseleave: function () {
this.tween('opacity', '0.5');
this.getPrevious(['.item_dz']).fade(1);
this.getPrevious(['.item_dz']).tween('background-color', '#f00', '#fff');
}
});
Current Jsfiddle code demo
Please help...
There are 2 things you are missing.
The first is that this code starting here
$$('.item').addEvent('mousedown', function (event){
event.stop();
is preventing this one to fire (since .delete is descendent of .item):
$$('.delete').addEvents({
click: function () {
this.getParent().destroy();
this.destroy();
},
This can be fixed by adding this line between the two I posted, to ignore the drag if the click was in the button
if (event.target == this.getParent().getElement('.delete button')) return;
The second problem is that you need to delegate the click event on the dropped element. You could do this like:
window.addEvent('click:relay(.delete)', function (){
this.getParent().destroy();
this.destroy();
})
So changing that you get this: http://jsfiddle.net/m6xDt/
About the sorting part I didn't get what you wanted. If you explain that better I will try to help with that also.
To make the cart sortable:
Start a new sortable class and then add each new item to it inside the onDrop event:
var mySortables = new Sortables('', {
clone: true,
opacity: 0.7
});
and then inside the onDrop:
mySortables.addLists(cart);
http://jsfiddle.net/m6xDt/
Related
I would like to know how can I the current list and the sorted list sending together with POST?
I got the results well, put the posting sending only one list. The problem is the currentlist VAR is outside of UPDATE. How can I find it?
<script type="text/javascript">
$(".wrapper").sortable({
handle: ".draghandler",
connectWith: $('.wrapper'),
distance: 100,
opacity: 0.4,
cursor: 'move',
start: function (event, ui) {
var currentlist = new Array(); //Aktuális sorrend lista
$('.draghandler').each(function() {
currentlist.push($(this).attr("id"));
$('#currentlist').html(currentlist);
});
},
update: function (event, ui) {
var newsortedlist = new Array(); //Átrendezett lista
$('.draghandler').each(function() {
newsortedlist.push($(this).attr("id"));
});
$('#newsortedoutput').html(newsortedlist);
//$('#responsefromserver').html('Rendezés mentése folyamatban');
**//'currentid': currentlist is outside of update:function, it is in start:function, therefore it dosen't send.**
$.post('/megrendelesek/sortmouse.php',{'currentid': currentlist, 'sortid': newsortedlist}, function(theResponse){
$('#responsefromserver').html(theResponse);
});
}
});
$(".wrapper").disableSelection();
$(".draghandler").disableSelection();
</script>
<div id="currentlist"></div>
<div id="newsortedoutput"></div>
<div id="responsefromserver"> </div>
To do what you require you need to store currentlist within scope of both function handlers. A global variable would do this, but is bad practice.
A better approach would be to store the array in a data attribute on the relevant .wrapper container. Then you can access this wherever necessary.
Also note that you can use the map() function to simplify creating the array from the drag handle id attributes.
$(".wrapper").sortable({
handle: ".draghandler",
connectWith: $('.wrapper'),
distance: 10, // reduced to 10 to make this demo easier to use
opacity: 0.4,
cursor: 'move',
start: function(e, ui) {
var currentlist = $('.draghandler').map((i, el) => el.id).get();
$(e.target).closest('.wrapper').data('currentlist', currentlist);
$('#currentlist').html(currentlist);
},
update: function(e, ui) {
var currentlist = $(e.target).closest('.wrapper').data('currentlist');
var newsortedlist = $('.draghandler').map((i, el) => el.id).get();
$('#newsortedoutput').html(newsortedlist);
// Commented as the AJAX call will cause an error in an SO snippet...
/*
$.post('/megrendelesek/sortmouse.php', {
'currentid': currentlist,
'sortid': newsortedlist
}, function(theResponse) {
$('#responsefromserver').html(theResponse);
});
*/
}
});
$(".wrapper").disableSelection();
$(".draghandler").disableSelection();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/jquery-ui-git.css" />
<div class="wrapper">
<div class="item">
Foo
<div class="draghandler" id="item-1">DRAG</div>
</div>
<div class="item">
Foo
<div class="draghandler" id="item-2">DRAG</div>
</div>
<div class="item">
Foo
<div class="draghandler" id="item-3">DRAG</div>
</div>
</div>
<br />
<div id="currentlist"></div>
<div id="newsortedoutput"></div>
<div id="responsefromserver"> </div>
I want to display a modal when a button is clicked but is not working. Here the code:
<button class="button is-warning is-pulled-right" onclick="refs.modalEdicion.open()">
<span>Editar</span>
</button>
<div class="modal" id="modalEdicion">
<div class="modal-background"></div>
<div class="modal-content">
<p class="image is-4by3">
<img src="https://bulma.io/images/placeholders/1280x960.png" alt="">
</p>
</div>
<button class="modal-close is-large" aria-label="close"></button>
</div>
Before starting, easy way to open modal should be like this;
yourElem.classList.toggle('is-active')
In my project, I have many modals. So I didn't always want to use like above. Because of this, I have created a basic modal event listener. I know this isn't enough for you. Because there will be other situations to open and close modals.
In this case, you can open and close your modals even you can listen to show and close events.
I used this Mozilla resource to create custom events. For example, you want to create two events called modal:show and modal:close. To make this, you should write some codes like below:
On Show Event
var event = new Event('modal:show')
yourElem.dispatchEvent(event);
On Close Event
var event = new Event('modal:close')
yourElem.dispatchEvent(event);
Now, we can listen to the above events.
An Example to Listen to Show Event
yourElem.addEventListener('modal:show', function() {
console.log("opened")
})
An Example to Listen to Close Event
yourElem.addEventListener("modal:close", function() {
console.log("closed")
})
We know how to open and close modal from easy way section. But sometimes users can click the modal background or "X" or Cancel buttons. If so, we need to handle these events. To make this we can use this code
var modalClose = yourelem.querySelectorAll("[data-bulma-modal='close'],
.modal-background")
modalClose.forEach(function(e) {
e.addEventListener("click", function() {
yourelem.classList.toggle('is-active')
var event = new Event('modal:close')
yourelem.dispatchEvent(event);
})
})
That's all. We know how to open or close a Bulma modal. Even we can listen to their show and close events. Let's make it a little simpler
Creating A BulmaModal Class
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)
}
}
Usage
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")
})
Let's look at this simple snippet
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")
})
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css" rel="stylesheet"/>
<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 active Modal</button>
I hope this answer will help Bulma newbies.
Bulma CSS is a CSS only framework and all the javascript behaviour has to be written manually. That means for a modal all the CSS classes for hiding and showing the modal has been written and you have to just bind the events properly. If you visit the Modal doc page (https://bulma.io/documentation/components/modal/) you can see a No Javascript warning stating that
Bulma does not include any JavaScript interaction. You will have to
implement the class toggle yourself.
Just define refs.modalEdicion.open function to add class is-active as per the doc and bind events on close button to remove the same CSS class. Optionally you might wish to bind the event to the overlay element as well if you want to dismiss modal by clicking the overlay.
Here is the desired implementation. https://codepen.io/anon/pen/KRaqxG
I ran into this problem this week and I found this link. It contains Official (according to it) Bulma Modal Doc page's javascript code. I copied and reduced it by a line or two and it works for all bulma modals you will have in your code.
Note that this is pretty open code. Ali's answer is ideal route to follow but if you don't want to spend time writing codes for modals, then just copy this segment in your code.
document.addEventListener('DOMContentLoaded', function () {
// Modals
var rootEl = document.documentElement;
var allModals = getAll('.modal');
var modalButtons = getAll('.modal-button');
var modalCloses = getAll('.modal-background, .modal-close, .modal-card-head .delete, .modal-card-foot .button');
if (modalButtons.length > 0) {
modalButtons.forEach(function (el) {
el.addEventListener('click', function () {
var target = document.getElementById(el.dataset.target);
rootEl.classList.add('is-clipped');
target.classList.add('is-active');
});
});
}
if (modalCloses.length > 0) {
modalCloses.forEach(function (el) {
el.addEventListener('click', function () {
closeModals();
});
});
}
document.addEventListener('keydown', function (event) {
var e = event || window.event;
if (e.keyCode === 27) {
closeModals();
}
});
function closeModals() {
rootEl.classList.remove('is-clipped');
allModals.forEach(function (el) {
el.classList.remove('is-active');
});
}
// Functions
function getAll(selector) {
return Array.prototype.slice.call(document.querySelectorAll(selector), 0);
}
});
Okay first of all, you need to have posted your javascript and css for a relevant answer but I'll outline the way I do it.
You could implement like below:
//One Modal
function OpenModal() {
//Get element with Id= "modal"
var modal = document.getElementById("modal");
//Change style to display = "block"
modal.style.display = "block";
}
//Multiple Modals
function OpenMore(n) {
//Get elements with class="modal" into an array
var modal = document.getElementsByClassName("modal");
//Change style of modal number [n] to display = "block"
modal[n].style.display = "block";
}
//This will close the modal once you click on it
window.onclick = function(event) {
//For single modal
var modal = document.getElementById("modal");
//If the click was on the modal the modal style display = "none"
if (event.target == modal) {
modal.style.display = "none";
}
//For multiple modals
var more = document.getElementsByClassName("modal");
//i represents which modal. It will go through all modals
for (var i = 0; i < more.length; i++) {
//If the click was on the modal for one of the modals display = "none"
//for all of them
if (event.target == more[i]) {
more[i].style.display = "none";
}
}
}
.modal {
display: none;
background-color: yellow;
height: 100vh;
width: 100vw;
position: fixed;
top: 0;
left: 0;
}
#modal {
display: none;
background-color: yellow;
height: 100vh;
width: 100vw;
position: fixed;
top: 0;
left: 0;
}
.button {
margin: 50px auto;
}
<!-- For One Modal -->
<button class="button" onclick="OpenModal()"> SingleModal </button>
<div id="modal"> hardidar </div>
<!-- For Multiple Modals -->
<button class="button" onclick="OpenMore(0)"> MultipleModal1 </button>
<div class="modal"> 1st Modal </div>
<button class="button" onclick="OpenMore(1)"> MultipleModal2 </button>
<div class="modal"> 2nd Modal </div>
The idea is that the initial display of the modal per the css rules is display: none once you click on the button the Javascript method will run and change this to display:block
You could change this behavior to do quite a bit. You could toggle a class you could change the transform: scale() which is my personal preference.
The example is a working one.
Try this code
$(document).ready(function() {
$("#your_id_button").click(function() {
$("#id_modal").addClass("is-active"); // modal is open
});
$("#your_id_button_close").click(function() {
$("#id_modal").removeClass("is-active"); // modal is close
});
});`
I'm trying to achieve a file drag-and-drop with knockout.js.
This is my html:
<div type="text" id="filedrag" class="" data-bind="event: {drop: function (data,e) { $root.insertFile(e,data);} }">
<div id="messages"></div>
</div>
And this my JS:
self.insertFile = function(e, data) {
console.log("insertfile called");
var files = e.target.files || e.dataTransfer.files;
console.log(files);
};
I copied the code from a jsfiddle. I don't quite see the difference between that one and mine. What am I doing wrong?
This is because you need to have a dragover event where you cancel the default behaviour.
The cancellation of the dragover event is needed to allow drop.
See https://developer.mozilla.org/en-US/docs/Web/Events/dragover.
I have created a fiddle with your code, updated with an dragover event where you cancel default behaviour.
Fiddle: http://jsfiddle.net/JBJd2/10/
HTML:
<div type="text" id="filedrag" class="drop_zone" data-bind="event: {
drop: function (data,e) { $root.insertFile(e,data);},
dragover: function(data, e){ $root.dragover(e);}
}">
<div id="messages"></div>
</div>
JS:
self.insertFile = function(e, data) {
e.preventDefault();
console.log("insertfile called");
var files = e.target.files || e.dataTransfer.files;
console.log(files);
};
self.dragover = function(e){
e.preventDefault();
}
I can't seem to bind to html5 drag and drop events.
Here's an example of from a template:
<script id="tabsTemplate" type="text/html">
<div class="dropzone" for="tab"
data-bind="event:{dragover: function(event){event.preventDefault();},
dragenter: function(event){event.target.addClass('dragover'); event.preventDefault();},
dragleave: function(event){event.target.removeClass('dragover'); event.preventDefault();}}
drop: function(event){console.log('blahblah!')}"></div>
<h1 class="tab" draggable="true"
data-bind="attr: {selected: $data.name === $item.selected()},
click: function(){$item.selected($data.name)},
event:{ dragstart: function(event){console.log('blah!!')},
dragend: function(event){document.getElementsByClassName('dragover')[0].removeClass('dragover')}}">
${name}
<img src="icons/close-black.png" class="close button" role="button"
data-bind="click: function(e){$item.close($data)}">
</h1>
</script>
What I have should work as expected... and it does as long as I make them normal inline ones. However, then the other bindings don't work!
I am getting this error message:
Uncaught SyntaxError: Unexpected token '||' jquery-tmpl.js:10
What's going on here? Is there something I'm doing wrong?
OK, I have worked it out. It seems I missed in the documentation where it said that in knockout, by default it makes all events prevent default / return false. So all I had to do was make my dragstart handler return true, and now it works. Phew!!
For those (like me) who need a SSCCE working; the solution follow's [cybermotron] suggestion, also fixes an issue where handlers expect prarameters data and event.
http://jsfiddle.net/marrok/m63aJ/
HTML
<script type="application/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<ul id="people" data-bind='template: { name: "personTmpl", foreach: people }'>
</ul>
<div class="trash" data-bind ="visible:dragging, event:{
dragover: function(data, event){
event.preventDefault();
},
drop: function(data, event){
console.log('trash', $root.drag_start_index())
$root.trash($root.drag_start_index())
event.preventDefault();
}
}"> <span>DELETE</span> </div>
<script id="personTmpl" type="text/html">
<li class="draggable" draggable="true" data-bind="event:{
dragstart: function(data, event){
$(event.target).addClass('dragSource')
$root.drag_start_index($index());
return $(event.target).hasClass('draggable');},
dragend: function(data, event){
$root.drag_start_index(-1);
$(event.target).removeClass('dragSource')
return true;
},
dragover: function(data, event){event.preventDefault();},
dragenter: function(data, event){
$root.drag_target_index($index());
var element = $(event.target)
if(element.hasClass('draggable'))
element.toggleClass('dragover');
event.preventDefault();
},
dragleave: function(data, event, $index){
var element = $(event.target)
if(element.hasClass('draggable'))
element.toggleClass('dragover');
event.preventDefault();
},
drop: function(data, event){
$(event.target).removeClass('dragover');
console.log('swap', $root.drag_start_index(), $root.drag_target_index() )
$root.swap($root.drag_start_index(), $root.drag_target_index())
}
}">
<span data-bind='text: name'></span>
</li>
</script>
Knockout
var Person = function(name) {
this.name = ko.observable(name);
};
var PeopleModel = function() {
var self = this;
self.drag_start_index = ko.observable();
self.drag_target_index = ko.observable();
self.dragging = ko.computed(function() {
return self.drag_start_index() >= 0;
});
self.people = ko.observableArray([
new Person("Oleh"), new Person("Nick C."), new Person("Don"), new Person("Ted"), new Person("Ben"), new Person("Joe"), new Person("Ali"), new Person("Ken"), new Person("Doug"), new Person("Ann"), new Person("Eve"), new Person("Hal")]);
self.trash = function(index) {
self.people.splice(index, 1)
}
self.swap = function(from, to) {
if (to > self.people().length - 1 || to < 0) return;
var fromObj = self.people()[from];
var toObj = self.people()[to];
self.people()[to] = fromObj;
self.people()[from] = toObj;
self.people.valueHasMutated()
}
};
ko.applyBindings(new PeopleModel());
You might have the same problem as mentioned here, although it refers to nested templates:
Warning
If you are passing templateOptions to the template binding from a nested template (so, specifying a template binding from within a template), then pay special attention to your syntax. You will encounter a problem, if your binding looks like this:
<div data-bind="template: { name: 'items', data: newItems, templateOptions: { header: “New Items!”}}"></div>
The jQuery Templates plugin gets confused by the }} at the end of your binding, since that is part of its syntax. Adding a space between your braces will work fine. Hopefully this prevents someone from a little unnecessary frustration.
<div data-bind="template: { name: 'items', data: newItems, templateOptions: { header: “New Items!”} }"></div>
I've got a jQuery code, which
$("a.reply").click(function() {
//code
});
When I click the link with .reply class the first time, nothing happens. The second time I click, the code inside the click function works.
The link is being inserted on the page using PHP from a mysql database. so it's not being inserted dynamically.
Why is this happening? Any solution?
The BadASS Code:
$(function(){
//TextArea Max Width
var textmaxwidth = $('#wrapper').css('width');
//Initialize Focus ids To Different Initially
var oldcommentid = -1;
var newcommentid = -2;
//End Of initialization
$("a.reply").click(function() {
newcommentid = $(this).attr('id');
if (newcommentid == oldcommentid)
{
oldcommentid=newcommentid;
$("#comment_body").focus();
}
else
{
$('#comment_form').fadeOut(0, function(){$(this).remove()});
var commetformcode = $('<form id="comment_form" action="post_comment.php" method="post"><textarea name="comment_body" id="comment_body" class="added_comment_body" rows="2"></textarea> <input type="hidden" name="parent_id" id="parent_id" value="0"/> <div id="submit_button"> <input type="submit" value="Share"/><input type="button" id="cancelbutton" value="Cancel"/></div></form>');
commetformcode.hide().insertAfter($(this)).fadeIn(300);
//
var id = $(this).attr("id");
$("#parent_id").attr("value", id);
oldcommentid=newcommentid;
//dynamicformcreation function
dynarun();
//
}
return false;
});
dynarun();
function dynarun()
{
//Form Re-Run Functions
$('#comment_body').elastic();
texthover();
$("#comment_form input, select, button").uniform();
textareasizer();
$("#comment_body").focus();
$("abbr.timestamp").timeago();
return false;
}
//TextArea Resizer Function
function textareasizer(){$("#comment_body").css('max-width', textmaxwidth);return false;}
//Other Miscellaneous Functions
$('.comment-holder').hover(
function(event) {
$(this).addClass('highlight');
},
function(event) {
$('.comment-holder').removeClass('highlight');
}
);
function texthover()
{
$('.added_comment_body').hover(
function(event) {
$(this).parent().parent().addClass('highlight');
},
function(event) {
$('.comment-holder').removeClass('highlight');
}
);
return false;
}
});
This is a longshot, but are you running some sort of tracking script? Like webtrends or coremetrics (or even some of your own script, that's globally looking for all clicks)? I ran into a similar problem a while ago, where the initial-click was being captured by coremetrics. Just a thought.
Does it still happen if you comment out all your code and simply have an alert("hi") inside the click function?
Update
I think Sarfaz has the right idea, but I would use the document ready function like so
$(document).ready(function(){
$("a.reply").click(function() {
//code
});
});
I just ran into same problem and I resolved my problem by removing:
<script src="bootstrap.js"></script>
you can use bootstrap.min.js
Use Inline CSS for hiding div and use JS/jQuery to show . This way Jquery Click Event will Fire On First Click
<div class="about-block">
<div class="title">About us</div>
<div class="" id="content-text" style="display:none;">
<p>Show me.</p>
</div>
</div>
<script>
var x = document.getElementById("content-text");
jQuery( '.about-block' ).click(function() {
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
});
</script>