当对外部事件应用过滤器时,无法再拖动到fullcalendar

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当对外部事件应用过滤器时,无法再拖动到fullcalendar相关的知识,希望对你有一定的参考价值。

我正在尝试将事件从外部事件框拖到fullcalendar。

我在下面的CodePen中重新创建了我面临的问题:

在第一次,将外部事件从列表拖动到日历中工作正常。但是,当我在搜索输入文本过滤器书籍中的书上应用过滤器时,我有以下问题。

以下是重现的步骤:

1-在搜索输入中查找111,将过滤到唯一生成的111事件簿。

2-正如你可以看到的那样,将这个结果事件从过滤器拖到日历中可以正常工作:但在这里我们主要感兴趣的是我们决定过滤但不要将任何东西拖入日历的情况。

3-所以现在将111过滤器作为搜索输入中的文本清除,外部事件框将返回所有默认事件,但这次尝试将其中一个拖入日历冻结。它不再有用了。 它会冻结所有外部事件,除了过滤器找到的最后一个事件意味着111事件(查看事件的最后一行)可以被拖动的事件。并且不能再将其他事件拖入日历中。

4-甚至如果我将111拖入日历中,之后如果我试图拖动另一个它会冻结。

html

<!DOCTYPE html>
<html ng-app="app">
  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <script data-require="angular.js@1.0.x" src="https://code.angularjs.org/1.3.15/angular.min.js" data-semver="1.0.7"></script>
    <script type="text/javascript" src="https://github.com/kamilkp/angular-vs-repeat/blob/master/dist/angular-vs-repeat.js"></script>
    <script src="https://code.angularjs.org/1.3.15/angular-animate.min.js"></script>
  </head>
<body ng-controller="MainCtrl">
<div id="first">
             <input type="search" id="myInput" ng-model="searchText" placeholder="filter books..." title="filter books"/>
             <div style="width:200px;display:inline-block;vertical-align:top;color: gray;">
                    <input type='checkbox' id='drop-remove' checked='checked'/>
                    <label for='drop-remove'> Remove after a drag </label>
             </div>
 <div id='external-events'>

             <ul vs-repeat="60" class="repeater-container" title="Books darggable(books.length)" data-                        drag="true"  data-jqyoui-options="revert: 'invalid'">
                 <li class="animate-repeat fc-event item-element" ng-repeat="book in books | orderBy : sort : false | filter:searchText as results track by book.contents.name"   id="book.id">

                   <div class="circle">book.contents['date']</div>
                   <div class="left content" ng-bind-html="trustAsHtml(book.contents['name'])" id="book_book.id"></div>
                   <div class="left rating">2/10</div>
                   <div class="clear"></div>
                </li>
                <li class="animate-repeat" ng-if="results.length === 0">
                    <strong>No results found...</strong>
                </li>

             </ul>
  </div>
</div>

<div id="second"> 
  <div id='calendar-container'>
    <div id='calendar'></div>
  </div>
</div>
</body>
</html>

js

var app = angular.module("app", ['ngAnimate']);
(function(angular) 
  'use strict';
app.controller("MainCtrl", ['$scope', '$sce', function($scope, $sce)

 $scope.books = [
                
                    id: 'id1',
                    contents: 
                        name: '<span>1Alain du sceau france</span><br><span> Canada Madagascar philipine</span>',
                        price: 'price1',
                        date: '111'
                    
                ,
                
                    id: 'id2',
                    contents: 
                        name: '<span>2Name zu Long zu Schreiben Bis Here ist Ein Beispiel</span><br><span>Maneschester Canada Madagascar philipine</span>',
                        price: 'price2',
                        date: '22'
                    
                ,
                
                    id: 'id3',
                    contents: 
                        name: '<span>3name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price3',
                        date: '23'
                    
                ,
                
                    id: '4',
                    contents: 
                        name: '<span>4name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price4',
                        date: '4'
                    
            ,
            
                    id: 'id5',
                    contents: 
                        name: '<span>5name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price5',
                        date: '5'
                    
            ,
            
                    id: 'id6',
                    contents: 
                        name: '<span>6name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price6',
                        date: '6'
                    
            ,
            
                    id: 'id7',
                    contents: 
                        name: '<span>7name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price7',
                        date: '7'
                    
            ,
            
                    id: 'id8',
                    contents: 
                        name: '<span>8name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price8',
                        date: '8'
                    
            ,
            
                    id: 'id9',
                    contents: 
                        name: '<span>9name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price9',
                        date: '9'
                    
            ,
               
                    id: 'id10',
                    contents: 
                        name: '<span>10Alain du sceau france</span><br><span> Canada Madagascar philipine</span>',
                        price: 'price10',
                        date: '10'
                    
                ,
                
                    id: 'id11',
                    contents: 
                        name: '<span>11Name zu Long zu Schreiben Bis Here ist Ein Beispiel</span><br><span>Maneschester Canada Madagascar philipine</span>',
                        price: 'price11',
                        date: '11'
                    
                ,
                
                    id: 'id12',
                    contents: 
                        name: '<span>12name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price12',
                        date: '12'
                    
                ,
                
                    id: 'id13',
                    contents: 
                        name: '<span>13name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price13',
                        date: '13'
                    
            ,
            
                    id: 'id14',
                    contents: 
                        name: '<span>14name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price14',
                        date: '14'
                    
            ,
            
                    id: 'id15',
                    contents: 
                        name: '<span>15name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price15',
                        date: '15'
                    
            ,
            
                    id: 'id16',
                    contents: 
                        name: '<span>16name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price16',
                        date: '16'
                    
            ,
            
                    id: 'id17',
                    contents: 
                        name: '<span>17name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price17',
                        date: '17'
                    
            ,
            
                    id: 'id18',
                    contents: 
                        name: '<span>18name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price18',
                        date: '18'
                    
            ,
            
                    id: 'id19',
                    contents: 
                        name: '<span>19name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price19',
                        date: '19'
                    
            ,
            
                    id: 'id20',
                    contents: 
                        name: '<span>20name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
                        price: 'price20',
                        date: '20'
                    
            
            ];





  /*$scope.books.forEach(function(book) 
    book.contents.name =  $sce.trustAsHtml(book.contents.name);
  )*/
  $scope.trustAsHtml = $sce.trustAsHtml;

  $scope.h = function(html) 
    return $sce.trustAsHtml(html);
  ;

  $scope.sort = function(num) 
    var newNum = parseInt(num.contents.date);
    console.log("$$newnum",newNum);
    return newNum;
  ;


 $(document).ready( function()     
        //Initialise external events
        initialise_external_event('.fc-event');
        initialise_calendar();

  );





  // initialize the external events
  // -----------------------------------------------------------------
function initialise_external_event(selector)

   /* initialize the external events
        -----------------------------------------------------------------*/

        $('#external-events .fc-event').each(function() 

            // store data so the calendar knows to render an event upon drop
            $(this).data('event', 
                title: $.trim($(this).text()), // use the element's text as the event title
                stick: true // maintain when user navigates (see docs on the renderEvent method)
            );

            // make the event draggable using jQuery UI
            $(this).draggable(
                zIndex: 999,
                revert: true,      // will cause the event to go back to its
                revertDuration: 0  //  original position after the drag
            );

        );




  function initialise_calendar()
     /* initialize the calendar
        -----------------------------------------------------------------*/

        $('#calendar').fullCalendar(
            header: 
                left: 'prev,next today',
                center: 'title',
                right: 'month,agendaWeek,agendaDay'
            ,
            editable: true,
            droppable: true, // this allows things to be dropped onto the calendar
            dragRevertDuration: 0,
            drop: function() 
                // is the "remove after drop" checkbox checked?
                if ($('#drop-remove').is(':checked')) 
                    // if so, remove the element from the "Draggable Events" list
                    $(this).remove();
                
            ,
            eventDragStop: function( event, jsEvent, ui, view ) 

                if(isEventOverDiv(jsEvent.clientX, jsEvent.clientY)) 
                    $('#calendar').fullCalendar('removeEvents', event._id);
                    var el = $( "<div class='fc-event'>" ).appendTo( '#external-events-listing' ).text( event.title );
                    el.draggable(
                      zIndex: 999,
                      revert: true, 
                      revertDuration: 0 
                    );
                    el.data('event',  title: event.title, id :event.id, stick: true );
                
            
        );


        var isEventOverDiv = function(x, y) 

            var external_events = $( '#external-events' );
            var offset = external_events.offset();
            offset.right = external_events.width() + offset.left;
            offset.bottom = external_events.height() + offset.top;

            // Compare
            if (x >= offset.left
                && y >= offset.top
                && x <= offset.right
                && y <= offset .bottom)  return true; 
            return false;

        
 

]);
)(window.angular);

css

    ul[title]::before 

    content: attr(title);
     /* then add some nice styling as needed, eg: */

     font: italic 11px "Trebuchet MS", Verdana, Arial, Helvetica,    sans-serif;
    color: gray;


/*ul 
  list-style-type: none;
*/

#myInput 
  /*background-image: url('/css/searchicon.png');*/
  background-position: 10px 12px;
  background-repeat: no-repeat;
  width: 77%;
  font-size: 16px;
  padding: 12px 20px 12px 40px;
  border: 1px solid #ddd;
  margin-bottom: 12px;


/*ul>li 
  display:block;
    padding-right: 0cm;
    margin-left: 0px;
*/

#calendar
 padding: 0 10px;
 width: 650px;
 float: right;
 margin: 0px 0px 10px 55px;
 

#external-events 
  width: 500px;
  padding: 0 0px;
  border: 0px solid #ccc;/* gray moyen*/
  background: #eee;/* #5D6D7E;(Blue mat) */ /* #eee color gray*/
  text-align: left;


#external-events .fc-event 
  cursor: pointer;
  z-index: 9999;
  background: #eee;
  border: solid 1px black;
  border-radius: 2px;
  margin-bottom:5px;


.content span

  color: gray;

.fc-event span:first-child

  font-size: 25px;
  font-weight: bold italic;


.content

  float:left;
  max-width:75%;


.clear

  clear:both;


.circle 
  float:left;
  width: 10%;
  height: 25%;
  padding: 0 10px;
  border-radius: 360px;


  /* Just making it pretty */
  @shadow: rgba(0, 0, 0, .1);
  @shadow-length: 4px;
  -webkit-box-shadow: 0 @shadow-length 0 0 @shadow;
          box-shadow: 0 @shadow-length 0 0 @shadow;
  text-shadow: 0 @shadow-length 0 @shadow;
  background: #FFFFFF;/*color white*/
  color: #f05907;/* color red*/
  font-family: Helvetica, Arial Black, sans;
  font-size: 10;
  text-align: center;


.rating

  float:right;
  background: #FFFFFF;/*color white*/
  color: #f05907;/* color red*/
  font-family: Helvetica, Arial Black, sans;
  font-size: 10;
  text-align: center;
  border-radius: 360px;


.animate-repeat 
  line-height:30px;
  list-style:none;
  box-sizing:border-box;


.animate-repeat.ng-move,
.animate-repeat.ng-enter,
.animate-repeat.ng-leave 
  transition:all linear 0.5s;


.animate-repeat.ng-leave.ng-leave-active,
.animate-repeat.ng-move,
.animate-repeat.ng-enter 
  opacity:0;
  max-height:0;


.animate-repeat.ng-leave,
.animate-repeat.ng-move.ng-move-active,
.animate-repeat.ng-enter.ng-enter-active 
  opacity:1;
  max-height:30px;



#first 
    width: 650px;
    float: left

#second 
    width: 650px;
    float: left;



.repeater-container
  height: 445px;
  overflow: auto;
  box-shadow: 0 0 10px;
  border-radius: 5px;
  list-style: none;
  margin: 0;
  padding: 0;
  -webkit-overflow-scrolling: touch;

.repeater-container .item-element 
    margin: 0 !important;
    width: 100%;
    height: 140px;
    border: 1px solid green;
    box-sizing: border-box;
    -moz-box-sizing: border-box;

答案

使用过滤器重复ng-recreats项目DOM。

不应该做的事情(正如你从我的HTML代码中看到的那样,我通过book.contents.name使用ng-repeat和track,据我所知)

那种情况下angularjs不会重新调整dom。否则,万一我们使用

通过id angularjs没有轨道的重复重复将重新调整你可以看到的dazxswpoi)。

我很难理解dom的确切原因

在这种情况下使用ng-repeat和过滤器重新创建!

我所做的解决方法在下面的文字中描述:

1-因此,为了使项目再次可拖动,我们必须在每个过滤器操作上调用.draggable()。

完美的解决方案是通过链接函数在角度指令中进行DOM操作。但是这里做的事情很简单一个解决方法我刚刚包含在detectEmpty中,这是一个范围函数。

2-添加ng-change =“detectEmpty()”以检测输入何时被清除

THE_FOLOWING_LINK

3-和.js

<input type="search" id="myInput" ng-model="searchText" placeholder="filter books..." title="filter books" ng-change="detectEmpty()"/>

希望它会帮助别人;)

希望AngularJS专家告诉我们为什么在这种情况下重建dom?

Update

因为之前提出的解决方案是一个糟糕的解

通过这样做每次应用过滤器时重新初始化外部事件:

$scope.detectEmpty = function() 
    if ($scope.searchText.trim().length === 0) 
         // it's empty
        $(document).ready( function()     


           initialise_external_event('.fc-event');

        );

    

Let's try to understand what's going on here?
=============================================
- All html elements loaded first.
- JS trigger all dragging functionality to loaded DOM.
- ng-repeat with filter function call to fetch new data and replace old 
  DOMs.
- Now drag functionality stops working.
- why? because JS drag function run on old DOM and currently it has been 
  removed. **why it has been moved ? I don't have any clue on that**
 - need to call the drag function again on new loaded DOM.
 - that's why added the call to initialise_external_event('.fc-event');
   when the input search is cleared. 

将每次向外部事件框添加其他外部事件。如果我们以20个条目的数组开始,我们将在下一个过滤器应用程序中得到40,并且每次应用过滤器时我们将向我们的exteranl数组条目添加20个条目。 20,40,60,80等......

问题是如何在使用ng-repeat和filter时保留DOM元素?

我有一个带过滤器的ng-repeat。

当某些项目被过滤器过滤掉,然后在另一个过滤器更改后恢复它们时,会为这些项目创建新的DOM元素。

如果项目上有任何DOM操作,则在隐藏项目并使用过滤器恢复后,它会丢失。

有没有办法保留DOM元素,即使过滤器删除了项目?

我尝试使用跟随$scope.detectEmpty = function() if ($scope.searchText.trim().length === 0) // it's empty $(document).ready( function() initialise_external_event('.fc-event'); ); 的轨道,但它没有帮助。

1-所以要观察DOM的变化并确认。您可以使用以下链接并使用LINK提供的服务

2-问题的根源是我试图在角度之外做这个。在角度内做所有事情时,angular会根据需要为我们更新DOM。

如果我们有复杂的DOM操作代码,听起来我们需要一个指令来处理它。然后我们只是将指令粘贴在这些元素上,DOM将根据需要进行更新。并获得深入信息,请参阅以下Basheer AL-MOMANI和这[JSFIDDLE]

link与答案有关。

3-我们还应该尝试使用angular指令实现拖放日历。为此,我们使用JqueryUI draggable。通过创建指令并通过“elem”传递属性。

4

我们在这里添加drag-me:

directive('dragMe', function() 
  return 
    restrict: 'A',
    link: function(scope, elem, attr, ctrl) 
      elem.data('event', 
          title: $.trim($(elem).text()), // use the element's text as the event title
          stick: true // maintain when user navigates (see docs on the renderEvent method)
        );
      elem.draggable(
          zIndex: 999,
          revert: true,      // will cause the event to go back to its
          revertDuration: 0  //  original position after the drag
        );
    
  ;
)

另一方面,我有一个元素,我将html绑定到它。

请参阅此链接上的<li class="animate-repeat fc-event item-element" drag-me ng-repeat="book in books | orderBy : sort : false | filter: searchText as results track by book.id" id="book.id" > 答案

我们添加compile =“book.contents.name”

在这里修改。 vkammerer使用指令来处理每次使用过滤器进行ng-repeat时我们的项目的可添加拖拽。

希望它会帮助别人;)

以上是关于当对外部事件应用过滤器时,无法再拖动到fullcalendar的主要内容,如果未能解决你的问题,请参考以下文章

无法从 MSIX 打包应用程序加载外部 DLL

是否正在拖动外部窗口?

无法在 FullCalendar 中拖动事件

jQuery UI 的贪婪 droppable 无法按预期工作

无法触发 drop 事件(是的,我在 dragover 中阻止了 Default()ed)

H5的拖放事件(拖拽删除)