https://imgur.com/Ek3CAOt
i want to quit the forbbiden cursor while im dragging an element. im using html5 default drag and drop. im using typescript
ive tried to change from ev.target.style.cursor to the "grab" cursor, i tried to change from dropEffect and so on, but none of them make the desire effect. here is the drag code.
<code>
drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
ev.dataTransfer.effectAllowed ="copy";
ev.dataTransfer.dropEffect = "move";
this.evdrag = ev.srcElement;
console.log(ev);
}
</code>
html template: < div [ngClass]="{'dragged': dragged}" class="btn dragword text-center text-lowercase"
style="font-size: 27px; color: rgb(115, 115, 115); height: 44px" id="Repellendus" draggable="true"
(dragstart)="drag($event);">Repellendus
typescript drop code:
<code>drop(ev, index) {
ev.preventDefault();
if (this.data != '') {
return;
}
this.optionHover1 = false;
this.data = ev.dataTransfer.getData("text");
this.evdrag.remove();
// ev.target.appendChild(document.getElementById(this.data));
this.checkAnswer(this.data, index);
}</code>
html template: <pre>< div [ngClass]="{'dragged': dragged}" class="btn dragword text-center text-lowercase"
style="font-size: 27px; color: rgb(115, 115, 115); height: 44px" id="Repellendus" draggable="true"
(dragstart)="drag($event);">Repellendus</ div></pre>
typescript drop code:
<code>drop(ev, index) {
ev.preventDefault();
if (this.data != '') {
return;
}
this.optionHover1 = false;
this.data = ev.dataTransfer.getData("text");
this.evdrag.remove();
// ev.target.appendChild(document.getElementById(this.data));
this.checkAnswer(this.data, index);
}</code>
With CSS in your stylesheet instead.
.dragging,
.dragword:active{
cursor:move!important;
}
Without a StackBlitz I can't really recreate this but here is another idea.
Template (view)
What about adding a dragging class for when it is being dragged?
<div [ngClass]="{'dragging': dragging, 'dragging':dragging}" class="btn dragword" id="Repellendus" draggable="true(dragstart)="drag($event);">Repellendus</div>
</pre>
TypeScript
What about adding the class during the drag event?
element.addEventListener("dragstart", function(event) {
// add `dragging` class
}, false);
element.addEventListener("dragend", function(event) {
// remove `dragging` class
}, false);
In Angular we'd use #Hostlistener though. Here is my personal StackBlitz reference for that.
Sidenote:
Does each dragword div have the same id? id="Repellendus" There must be several of these right?
Related
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 using this code : http://codepen.io/andytran/pen/xweoPN/ to create an information card slider but i think the code <div class="card"> is having some problems when put in a modal.
I've created a pen with my current code, Kindly review it and suggest the changes to remove that blank card while clicking on the modal. https://codepen.io/anon/pen/bWmYxN
In the first card a blank card with the text how it works is present, how to remove that blank card?
I am not quite familiar with the libraries that you used here. But anyway, something like this can fix your issue if nothing else works out.
$("#modalBtn").click(function() {
setTimeout(
function(){
$("#next").click();
}, 250
);
});
EDIT:
Sorry about that, I forgot that you should add an ID to your button that calls the modal.
<button id="modalBtn" type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
you just need to put this code only in $(document).ready
window.setTimeout(function() {
$('#myModal.products').height(283);
},200);
so your jquery code will be
$(document).ready(function() {
window.setTimeout(function() {
$('#myModal.products').height(283);
},200);
var getProductHeight = $('.product.active').height();
$('.products').css({
height: getProductHeight
});
function calcProductHeight() {
getProductHeight = $('.product.active').height();
$('.products').css({
height: getProductHeight
});
}
function animateContentColor() {
var getProductColor = $('.product.active').attr('product-color');
$('body').css({
background: getProductColor
});
$('.title').css({
color: getProductColor
});
$('.btn').css({
color: getProductColor
});
}
var productItem = $('.product'),
productCurrentItem = productItem.filter('.active');
$('#next').on('click', function(e) {
e.preventDefault();
var nextItem = productCurrentItem.next();
productCurrentItem.removeClass('active');
if (nextItem.length) {
productCurrentItem = nextItem.addClass('active');
} else {
productCurrentItem = productItem.first().addClass('active');
}
calcProductHeight();
animateContentColor();
});
$('#prev').on('click', function(e) {
e.preventDefault();
var prevItem = productCurrentItem.prev();
productCurrentItem.removeClass('active');
if (prevItem.length) {
productCurrentItem = prevItem.addClass('active');
} else {
productCurrentItem = productItem.last().addClass('active');
}
calcProductHeight();
animateContentColor();
});
// Ripple
$('[ripple]').on('click', function(e) {
var rippleDiv = $('<div class="ripple" />'),
rippleSize = 60,
rippleOffset = $(this).offset(),
rippleY = e.pageY - rippleOffset.top,
rippleX = e.pageX - rippleOffset.left,
ripple = $('.ripple');
rippleDiv.css({
top: rippleY - (rippleSize / 2),
left: rippleX - (rippleSize / 2),
background: $(this).attr("ripple-color")
}).appendTo($(this));
window.setTimeout(function() {
rippleDiv.remove();
}, 1900);
});
});
Thats it
Hope this helps
The problem was I forgot assigning the active class to the product class
<div class="product-active">
this will make the first screen to appear and if there's no active class, then it'll show a blank screen since it doesn't know what to show. A small typo got me on feet. Anyways, this is for the future reference if anyone makes a silly mistake like this.
Thanks.
Here is my angular2 code.
Template
<div #picker class="slider">
<div class="slider-track">
<div #sliderSelectionEl class="slider-selection"></div>
<div #sliderHandle1 class="slider-handle"></div>
<div #sliderHandle2 class="slider-handle"></div>
</div>
<div #tooltipEl class="tooltip">
<div class="tooltip-arrow"></div>
<div #tooltipInner class="tooltip-inner"></div>
</div>
<input type="text" class="span2" value="" id="sl2"><br/>
</div>
Component
import {Component, OnInit, Input, ViewChild, ElementRef, Renderer} from '#angular/core';
export class SliderComponent implements OnInit {
#ViewChild('picker') picker: ElementRef;
constructor(private renderer: Renderer, private el: ElementRef) {
}
ngAfterViewInit() {
this.renderer.setElementClass(this.picker.nativeElement, 'slider-horizontal', true);
console.log(this.picker.nativeElement.offsetWidth);
console.log(this.picker.nativeElement.offsetHeight);
}
}
.slider-horizontal {
width: 210px;
height: 20px;
}
The problem is the printed values are different for each time loading. I guess this issue is due to the browser have not completed loading the div. Do you know what is the solution for this?
You can detect size changes by using
MutationObserver
Probably the biggest audience for this new api are the people that
write JS frameworks, [...] Another use case would be situations where you are using frameworks that manipulate the DOM and need to react to these
modifications efficiently ( and without setTimeout hacks! ).
Here is how you can use it to detect changes in elements :
// select the target node
var target = document.querySelector('#some-id'); // or
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true }
// pass in the target node, as well as the observer options
observer.observe(target, config);
// later, you can stop observing
observer.disconnect();
For your case, you could use it inside your ngAfterViewInit and refresh your offsets size. You can be more specific and only detect some mutations, and only then extract your offsets.
more info :
doc: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
compatibility : https://caniuse.com/#feat=mutationobserver
Demo:
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation);
if(mutation.attributeName == 'class') // detect class change
/*
or if(mutation.target.clientWidth == myWidth)
*/
showOffset(mutation.target);
observer.disconnect();
});
});
var config = { attributes: true}
var demoDiv = document.getElementById('demoDiv');
var logs = document.getElementById('logs');
// wait for document state to be complete
if (document.readyState === "complete") {
ngAfterViewInit();
}
document.onreadystatechange = function () {
if (document.readyState === "complete") {
ngAfterViewInit();
}
}
// observe changes that effects demoDiv + add class
function ngAfterViewInit(){
observer.observe(demoDiv, config);
demoDiv.classList.add('slider-horizontal');
}
// show offsetWidth + height.
// N.B offset width and height will be bigger than clientWidth because I added a border. If you remove the border you'll see 220px,20px
function showOffset(element){
offsetMessage = "offsetWidth:" + demoDiv.offsetWidth + " offsetHeight: " + demoDiv.offsetHeight;
console.log(offsetMessage);
logs.innerHTML = offsetMessage;
}
.slider-horizontal {
border: 2px solid red;
width: 210px;
height: 20px;
background: grey;
}
<div id='demoDiv'> I am a demo div </div>
<div style="margin-top: 20px;"> logs : <span id='logs' style=" padding: 5px; border: 1px solid black"></span></div>
You have to schedule calls to 'offsetWidth' after rendering cycle, angular executes draw on the end of microtask queue, so you could try setTimeout(..., 0) or run Promise.resolve().then(...) outside of zonejs. Hope it helps.
In order to get correct offset values you can use: ngAfterContentChecked with the AfterContentChecked Interface.
This method is called after every change detection run. So, inside this method use a flag (or counter) and setTimeOut:
if (this.counter <= 10) {
// this print offsetwidth of my element
console.log('mm ' + this.container.nativeElement.offsetWidth);
// setTimeOut allow to run another changedetection
// so ngAfterContentChecked will run again
setTimeout(() => { }, 0);
//you could use a counter or a flag in order to stop getting the right width
this.counter++;
}
Hope it helps! Feel free to comment
I am trying to use css style in directive, the style is coming but it is not coming continuously when I am clicking the button.
For example, I have a button and a css style(bouncing style) and also I am having a directive.
If I click that button many times that bouncing style also have to come continuously , but I am not getting the style continuously.
I also used $watch in that also only once the style is coming.
<div class="row">
<button class="btn btn-primary" ng-click="qty=qty-1">-</button>
<span my-directive="qty" class="box " ng-bind="qty">{{qty}}</span>
<button id="target" class="btn btn-primary" ng-click="qty=qty+1">+</button>
angular.module('docsSimpleDirective', []).controller('Controller', ['$scope', function($scope) {
$scope.qty =1; }]).directive('myDirective', function() {
return {
restrict:'A',
link:function(scope,elem,attr){
var btn = document.getElementById('target');
btn.addEventListener('click', moveMe);
function moveMe() {
console.log("coming to move");
elem.addClass('bounce');
}
/* scope.$watch(attr.myDirective, function (newValue, oldValue) {
if (newValue !== oldValue) {
console.log("$watch");
console.log(newValue, oldValue);
elem.addClass('bounce');
}
});*/
}
}; });
Here is my plunker
Can you please solve my problem?
Thanks in advance!
You need to remove class bounce after execution of moveMe function. Can use callback function.
function moveMe() {
console.log("coming to move");
elem.addClass('bounce');
setTimeout(function() {
elem.removeClass('bounce');
}, 1000);
}
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>