change the dropEffect of a drag - javascript

I am using ngx drag and drop which is using the default HTML5 dnd api.
I have a list of object, when I move them, my event and the drop effect are type "copy"
I am trying to find a way to make the event be a "move" instead because that what is the drag and drop action supposed to be, and I want my OnMove event to fire
I tried change when I start the drag
onDragStart(event:DragEvent, card:KanbanCard) {
event.dataTransfer.dropEffect = "move";
event.preventDefault();
}
But this doesn't work
<div class="kanban-column-container">
<p class="title"><strong>{{column.name}}</strong></p>
<button mat-button (click)="addCard();">Add Card</button>
<div class="list"
dndDropzone
(dndDrop)="onDrop($event)">
<!-- PLACEHOLDER for drag & drop. Removed on DOM LOAD AUTOMATICALLY -->
<div class="card-placeholder" dndPlaceholderRef>
placeholder
</div>
<div *ngFor="let card of _cards"
[dndDraggable]="card"
(dndEffectAllowed)="move"
(dndStart)="onDragStart($event, card)"
(dndCanceled)="onDragCanceled($event, card)"
(dndMoved)="onMoved($event)"
(dndEnd)="onDragEnd($event, card)"
[hidden]="card.hidden">
<kanban-card-component [card]="card"></kanban-card-component>
</div>
</div>

Basicly u did it wrong.
first of it suppose to be [] and not () cos its not a function.
secound if you want to put a value it soppuse to be like you put and Object so this way will work.
<div class="kanban-column-container">
<p class="title"><strong>{{column.name}}</strong></p>
<button mat-button (click)="addCard();">Add Card</button>
<div class="list"
dndDropzone
(dndDrop)="onDrop($event)">
<!-- PLACEHOLDER for drag & drop. Removed on DOM LOAD AUTOMATICALLY -->
<div class="card-placeholder" dndPlaceholderRef>
placeholder
</div>
<div *ngFor="let card of _cards"
[dndDraggable]="card"
[dndEffectAllowed]="'move'" <-- like this
(dndStart)="onDragStart($event, card)"
(dndCanceled)="onDragCanceled($event, card)"
(dndMoved)="onMoved($event)"
(dndEnd)="onDragEnd($event, card)"
[hidden]="card.hidden">
<kanban-card-component [card]="card"></kanban-card-component>
</div>
</div>

Related

How to use the same function for different buttons to display their own dropdown lists

I am going to have multiple dropdown buttons to show their own dropdown lists. In HTML, the dropdown lists are the sibling elements of buttons. When I use the querySelector and click whichever button, the first buttons dropdown list shows up naturally. Which selector should I use instead or any other solutions? How can I use buttonDropdown() function for each button?
Thanks in advance.
<div class="container">
<button class="dropdown-button">
<!-- content -->
</button>
<div class="dropdown-button-list">
<!-- content -->
</div>
</div>
const dropdownButton = document.querySelector('.dropdown-button')
dropdownButton.addEventListener('click', showDropdown)
function showDropdown() {
document.querySelector.('dropdown-button-list').classList.add('show')
}
If you associate them together inside of an element (like I used class='dropdown-group') then you can easily find the associated list to the button by utilizing an event listener and
evt.target.closest('.dropdown-group').querySelector('.dropdown-button-list')
window.addEventListener('load', () => {
document.querySelectorAll('.dropdown-button').forEach(el => el.addEventListener('click', e => buttonDropdown))
})
function buttonDropdown(evt) {
// button is evt.target
// associated dropdown is:
// evt.target.closest('.dropdown-group').querySelector('.dropdown-button-list')
}
<div class="container">
<div class='dropdown-group'>
<button class="dropdown-button">
<!-- content -->
</button>
<div class="dropdown-button-list">
<!-- content -->
</div>
</div>
</div>

Retain scroll position when a button is toggled

I am working on an angularJS application which has a page where I display around 30 items using ng-repeat. In front of each item, there is a toggle button (enabled/disabled). With the current code that I have, I can toggle these items. But the problem is if I scroll down and toggle lets say item 25, then automatically it scrolls to the top of the page. If I now scroll down, I can see that the toggle actually took place.
So the requirement now is to make sure that the scroll position is retained after the toggle button is clicked.
Please see below the code that I have.
HTML
<div id="eventTypes" class="panel-body">
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
<div ng-if="spinner" class="spinner">
<div class="spinner-container container1">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container2">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container3">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
</div>
</div>
JS
(function () {
'use strict';
angular.module('myApp').controller('itemsController', function ($scope, itemsService) {
var serviceError = function (errorMsg) {
console.log(errorMsg);
$scope.turnOffSpinner();
};
$scope.items = [];
$scope.item = {};
$scope.spinner = true;
$scope.toggleEnabled = function (item) {
$scope.turnOnSpinner();
itemsService.toggleEnabled(item)
.then(function () {
$scope.loaditems();
});
};
$scope.loaditems = function () {
itemsService.getitems().then(function (response) {
$scope.items = response.data;
}, serviceError);
$scope.turnOffSpinner();
};
$scope.turnOnSpinner = function () {
$scope.spinner = true;
};
$scope.turnOffSpinner = function () {
$scope.spinner = false;
};
$scope.loaditems();
});
}());
How this works right now is, once I click the toggle button, a spinner is enabled. Meanwhile the controller will call the itemService.toggleEnabled() method which does an ajax call to the server to just change the status of the item(enabled to disabled or vice-versa) in the backend. On successful change of the status and when the ajax call returns, the $scope.loadItems() method is called in the controller. This method will then do another ajax call to fetch the items (now with the updated status of the item that was toggled). The spinner is disabled and the data is then displayed on the UI.
When all of this is done, the page is scrolled to the top. This is annoying when I want to toggle an item which is way down in the list.
I want the page to be present at the same position when I clicked the toggle button of the corresponding item and not scrolling up to the top.
I am new to AngularJS and any help in this regard would be really helpful.
It looks like your spinner scheme is what's causing you problems:
...
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
...
<div ng-if="spinner" class="spinner">
...
Whenever you click your button, you are removing every single element in your ng-repeat from the DOM when you $scope.turnOnSpinner(). That's why it appears to jump to the top. It's not really jumping, there just aren't enough DOM elements to fill up the page, making the page so short that the scrollbar disappears (even if it's only for a second). Then when the spinner is done, your ng-repeat fills up the page with DOM elements again, resulting in your scroll position being lost.
So basically what you are trying to fix is a symptom of a less than ideal loading spinner implementation.
ng-if is a "brutal" way of hiding things in Angular. It's mostly meant to hide things for a longer period of time than "softer" directives like ng-show/ng-hide. One solution to your problem is to use ng-disabled on each one of your buttons to prevent the user from interacting with it while the spinner is active, rather than doing a hard removal of each element:
Before:
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
After:
<div ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
ng-disabled="spinner"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
Another solution, which I really like and use myself is this Angular module: https://github.com/darthwade/angular-loading
You can attach it to any element in the page and it will put a loading spinner over it and prevent you from interacting with it until your ajax or whatever is done.
If you don't like either of those, try putting your ng-repeat into a container that you can use to prevent interaction with your elements when the spinner is up:
<div class="container" ng-class="{'you-cant-touch-this': spinner}">
<div ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
</div>
Now you can style it in some way to prevent interaction without having to remove all those items from the DOM:
.you-cant-touch-this {
pointer-events: none;
}

Remove class from buttons on changing values in editable div for dynamically generated divs

I am creating an app using knockout and jquery. There are user generated contents which a user can edit and save. I have a save button which is disabled and gets enabled only when new character is added to the editable div.
Problem:
Save button gets activated for all divs. I want only the respective button to get enabled and remaining should stay in disabled state.
HTML:
<div data-bind="foreach: $root.goals">
<div class="ui padded segment mainCard brdR-S" data-bind="attr:{id:Title()}">
<div>
<div>
<div contenteditable="true" class="heading pdM-TB wordwrap" data-bind="attr:{href:'#'+Title()}, editableText: Title, event: { keyup: $root.ShowButtons }" id="goalTitle">
</div>
<div class="mgXl-T pdM-TB">
<button class="ui disabled tiny primary button" id="btnSave" data-bind="click: $root.putGoal">
<i class="refresh icon"></i>Save
</button>
</div>
</div>
</div>
</div>
Jquery
self.ShowButtons = function (data, e) {
$('.button').removeClass('disabled')
};

Show/hide multiple children classes for an individual parent click (Jquery)

I'm fairly new to Javascript/Jquery and I'm trying to hide multiple children/adjacent classes when a specific parent class is clicked.
Here's my HTML
<div class="container">
<div class="row">
<div class ="col-md-2 pov_icon">
<div class="pov_icon_small">
<i class="fa fa-clock-o"></i>
</div>
<div class="pov_title_small">
MEASURE
</div>
</div>
<div class ="col-md-2 pov_icon">
<div class="pov_icon_large">
<i class="fa fa-map-marker"></i>
</div>
<div class="pov_title_large">
MEASURE
</div>
</div>
<div class ="col-md-2 pov_icon">
<div class="pov_icon_small">
<i class="fa fa-commenting"></i>
</div>
<div class="pov_title_small">
MEASURE
</div>
</div>
</div>
</div>
What I'm aiming to do is: When a user clicks one of the two smaller icons shown (pov_icon_small), for that individual icon: the classes pov_icon_small and pov_title_small will change to pov_icon_large and pov_title_large respectively. In the same time, I want the other 'large' icon and 'title' to revert back to the 'small' state
I've started calling some Javascript but I don't think I'm headed the right way:
$('.pov_icon_small').on('click', function (e) {
$(this).toggleClass("pov_icon_large");
});
Would anyone be willing to point me to the right direction?
To use individual click
$('.pov_icon_small , .pov_icon_large').on('click', function (e) {
$('.pov_icon_large').not($(this)).removeClass('pov_icon_large').addClass('pov_icon_small');
$(this).toggleClass("pov_icon_small").toggleClass("pov_icon_large");
});
and for title the same way
$('.pov_title_small , .pov_title_large').on('click', function (e) {
$('.pov_title_large').not($(this)).removeClass('pov_title_large').addClass('pov_title_small');
$(this).toggleClass("pov_title_small").toggleClass("pov_title_large");
});
Working Demo
To run both action on icon click use this
$('.pov_icon_small , .pov_icon_large').on('click', function () {
$('.pov_icon_large').not($(this)).removeClass('pov_icon_large').addClass('pov_icon_small');
$('.pov_title_large').not($(this).next('div[class^="pov_title_"]')).removeClass('pov_title_large').addClass('pov_title_small');
$(this).toggleClass("pov_icon_small").toggleClass("pov_icon_large");
$(this).next('div[class^="pov_title_"]').toggleClass("pov_title_small").toggleClass("pov_title_large");
});
Working Demo
Note: be sure to include Jquery
You can add a common class icon for the icon div and title for the title div and following code will work,
$(".pov_icon_small").on('click',function(){
$(this).parent().siblings().children('div').each(function(value){
if($(this).hasClass('icon'))
$(this).addClass('pov_icon_small').removeClass('pov_icon_large');
else if($(this).hasClass('title'))
$(this).addClass('pov_title_small').removeClass('pov_title_large');
});
$(this).addClass('pov_icon_large').removeClass('pov_icon_small');
$(this).siblings('.title').addClass('pov_title_large').removeClass('pov_title_small');
});
Here as you can see, I am first getting parent of the icon clicked i.e. Your pav_icon div now I am changing for all the siblings now each div in the sibling. If it is Iicon changing icon classes as required if title changing title classes.

Find sibling with Javascript and Hammer.js

I have made a simple system which detects double taps. I want to show a heart icon when someone double taps on an image, just like on Instagram.
This is what my code looks right now:
var elements = document.getElementsByClassName('snap_img');
[].slice.call(elements).forEach(function(element) {
var hammertime = new Hammer(element),
img_src = element.getAttribute('src');
hammertime.on('doubletap', function(event) {
alert(img_src); // this is to test if doubletap works
// Some javascript to show the heart icon
});
});
This is what the HTML looks like:
<div class="snap_item">
<div class="snap_item_following_info">
<img class="snap_item_following_img" src="res/stat/img/user/profile/small/1.fw.png" alt="#JohnDoe" />
<a class="snap_item_following_name" href="#">#JohnDoe</a>
<div class="snap_too">
</div>
</div>
<img class="snap_img" src="res/stat/img/user/snap/43/2.fw.png" alt="#ErolSimsir" />
<div class="like_heart"></div>
<div class="snap_info">
<div class="snap_text">
LA is the shit...
<a class="snap_text_hashtah" href="#">#LA_city_trip</a>
</div>
<div class="snap_sub_info">
<span class="snap_time">56 minutes ago</span>
<div class="like inactive_like">
<div class="like_icon"></div>
<div class="like_no_active">5477</div>
</div>
</div>
</div>
</div>
So when the element 'snap_img' is double tapped, I need to get the element 'like_heart' which is one line below the snap_img element. How do I get that sibling element and fade it in with JQuery?
Like this
[].slice.call(elements).forEach(function(element) {
var hammertime = new Hammer(element),
img_src = element.getAttribute('src');
hammertime.on('doubletap', function(event) {
alert(img_src); // this is to test if doubletap works
$(element).next().text('♥').hide().fadeIn();
});
});
P.S. I've added that heart text, since the sibling was empty.
On the event handler, i would do $(element).parent().find('.like_heart').fadeIn(); So the code is not dependant on the element ordering.
(To clarify to selector: take the parent element which is the div.snap_item and find an element with class like-heart inside it)

Categories