2013-02-19 4 views
2

Немного фонеBackbone: удалить Ellipsis OnClick

Я пытаюсь создать твиттер как корм, где чириканье/строка будет расширяться OnClick, раскрывая больше информации.

Данные извлекаются из файла JSON (отправляются с внутренней стороны на интерфейс). Я использую магистраль для визуализации данных на интерфейсе.

Скажем, мой канал отображает 10 строк, каждая строка отображает несколько данных, а затем добавляет строку/div, чтобы показать больше информации. Поле описания содержит довольно много текста, поэтому я использую эллипсис JavaScript на нем. Я использую многоточие Javascript, так как краткое описание должно быть более чем одной строки (не думайте, что эллипсис CSS работает более чем в одной строке).

  1. Я создал плагин, который будет обрезать текст описания и OnClick Я хочу удалить многоточие и заменить его полным описанием (так как строка будет расширяться).

  2. Я создал плагин, который сохранит полное описание (до его усечения) в массив.

Выпуск

Моя идея состояла в том, чтобы сравнить индекс строки щелкнул (currentTarget) к индексу строк, сохраненных (в массиве), а затем заменить текст многоточия с полным описанием, то разверните div с анимацией jQuery.

Я не уверен, есть ли способ получить индекс из основного «события клика» (чтобы сравнить его с индексом, сохраненным в массиве)?

Не стесняйтесь, дайте мне знать, если есть лучший способ приблизиться к этому.

Заранее спасибо

Вот мой код:

Округление & сохранить оригинальные текстовые функции

/** 
* Plugins 
*/ 
var arr = []; 

$.fn.truncate = function(){ 
    return this.each(function(index,element){ 
     var elementText = $(element).text(); 
     if(elementText.length > 165){ 
      var truncated = elementText.trim().substring(0, 165).split(" ").slice(0, -1).join(" ") + "…"; 
     } 
     $(element).text(truncated); 
    }); 
}; 

$.fn.getText = function(){ 
    return this.each(function(index,element){ 
     arr.push({ 
      i: index, 
      v: $(element).text() 
     }); 
    }); 
}; 

Backbone Модель & Коллекции

/** 
* Model 
*/ 
var Task = Backbone.Model.extend(); 

/** 
* Collections 
*/ 
var RecentTasksList = Backbone.Collection.extend({ 
    model: Task, 
    url: 'json/recentTasks.json' 
}); 

Backbone Просмотров

/** 
* Views 
*/ 
var RecentTasksView = Backbone.View.extend({ 
    el: '.taskList', 
    template: _.template($('#recentTasksTemplate').html()), 
    render: function(){ 
     _.each(this.model.models, function(data){ 
      this.$el.append(this.template(data.toJSON())); 
     }, this); 

     $('.description').getText(); 
     $('.description').truncate(); 

     return this; 
    } 
}); 

var FullTaskView = Backbone.View.extend({ 
    el: '.taskContainer', 
    events: { 
     'click .task': 'showFullDetails' 
    }, 
    showFullDetails: function(e){ 
     var eTarget = $(e.currentTarget); 
     var $desc = $('.description'); 

     if(eTarget.hasClass('expanded')){ 
      eTarget.animate({ 
       'height': '80px' 
      }, 
      function(){ 
       eTarget.removeClass('expanded'); 
      }); 
     } 
     else{ 
      console.log($(eTarget).find($desc).html()); 

      eTarget.animate({ 
       //doesn't work lesser IE 8 
       'height': eTarget[0].scrollHeight 
      }, 
      function(){ 
       eTarget.addClass('expanded'); 
      });  
     } 
    } 
}); 

var AppView = Backbone.View.extend({ 
    el: 'body', 
    initialize: function(){ 
     //Recent Tasks 
     var recentTasksList = new RecentTasksList(); 
     var recentTasksView = new RecentTasksView({ 
      model: recentTasksList 
     }); 
     recentTasksList.bind('reset', function(){ 
      recentTasksView.render(); 
     }); 
     recentTasksList.fetch(); 

     //Full Task Details 
     var fullTaskView = new FullTaskView(); 
    } 
}); 

var appView = new AppView(); 

Underscore шаблону

<script id="recentTasksTemplate" type="text/template"> 
    <div class="task clearfix"> 
     <div class="image"> 
      <img src="<%= image %>" /> 
     </div> 
     <div class="details"> 
      <h3 class="title"><%= title %></h3> 
      <div class="description"> 
       <%= description %> 
      </div> 
     </div> 
    <div> 
</script> 

HTML

<div class="taskContainer"> 
    <div class="taskList"></div> 
</div> 

EDIT

Последний вопрос. Я добавил вкладку на свою страницу (аналогичный призыв к действию). Тот же тип информации будет отображаться onclick (я использую тот же шаблон). Например, теперь у меня есть LastTask и PopularTask. Я создал представление для вкладок, содержащих события click. Нужно ли мне вводить модель &? & извлекать данные каждый раз или я могу повторно использовать те, которые уже инициализированы?

Я создал новый вид второй вкладки. Grabbing JSON файл с сервера:

var PopularTasksList = Backbone.Collection.extend({ 
    model: Task, 
    url: 'json/popularTasks.json' 
}); 

var PopularTasksView = Backbone.View.extend({ 
    el: '.taskList', 
    render: function(){ 
     $('.taskList').empty(); 
     _.each(this.model.models, function(model){ 
      var taskView = new TaskView({model: model}); 
      this.$el.append(taskView.render().el); 
     }, this); 
     return this; 
    } 
}); 

Затем я создал представление табуляции, в котором будут показаны правильные задачи onclick.

var TabsView = Backbone.View.extend({ 
      el: 'body', 
      events:{ 
       'click .tabRecent': 'fetchDataRecentTasks', 
       'click .tabPopular': 'fetchDataPopularTasks' 
      }, 
      fetchDataRecentTasks: function(){ 
       var recentTasksList = new RecentTasksList(); 
       var recentTasksView = new RecentTasksView({ 
        model: recentTasksList 
       }); 
       recentTasksList.bind('reset', function(){ 
        recentTasksView.render(); 
       }); 
       recentTasksList.fetch(); 
      }, 
      fetchDataPopularTasks: function(){ 
       var popularTasksList = new PopularTasksList(); 
       var popularTasksView = new PopularTasksView({ 
        model: popularTasksList 
       });  
       popularTasksList.bind('reset', function(){ 
        popularTasksView.render(); 
       }); 
       popularTasksList.fetch(); 
      } 
     }); 
+0

Похоже на сложность использования 2 плагинов и 2 библиотек для управления задачей, когда один плагин может обрабатывать все это. Вы можете сохранить текст внутри самого элемента, используя метод data(), и одновременно добавить обработчики и классы событий. – charlietfl

+0

Почему бы не разместить многоточие в пролете? затем, когда ваш пользователь нажимает, чтобы просмотреть полный контент, используйте это событие click, чтобы удалить диапазон многоточия для текущей записи. – chrisvillanueva

+0

не уверен, что это может помочь ... http://dotdotdot.frebsite.nl/ – Greg

ответ

2

Я думаю, вам следует создать новое представление для отдельной задачи. Затем с этой точки зрения вы можете обрабатывать клик, так что у вас есть доступ к модели задач, а также доступ к DOM этого представления очень легко.

Тогда вы можете избавиться от своего FullTaskView и плагинов jQuery.

/** 
* Model 
*/ 
var Task = Backbone.Model.extend({ 
    getShortDescription: function(){ 
     var desc = this.get('description'); 
     if(desc.length > 165){ 
     return desc.trim().substring(0, 165).split(" ").slice(0, -1).join(" ") + "…"; 
     } 
     return desc; 
    } 
}); 

Добавить новый TaskView и изменить RecentTasksView для их создания и рендеринга.

/** 
* Views 
*/ 

var TaskView = Backbone.View.extend({ 
    template: _.template($('#recentTasksTemplate').html()), 
    events: { 
     'click': 'showFullDetails' 
    }, 
    render: function(){ 
     // pass the model json, plus the short description to the template 
     this.$el.html(this.template({ 
      data: this.model.toJSON(), 
      shortDesc: this.model.getShortDescription() 
      })); 

     return this; 
    }, 
    showFullDetails: function(){ 
     // change text, show/hide, animate here 
     // In the view, this.$() will only match elements within this view. 

     // if expand... 
     this.$('.description').html(this.model.get('description')); 

     // if hide... 
     this.$('.description').html(this.model.getShortDescription()); 
    } 
}); 
var RecentTasksView = Backbone.View.extend({ 
    el: '.taskList', 
    render: function(){ 
     _.each(this.model.models, function(model){ 
      // create a view for each task, render and append it 
      var taskView = new TaskView({model: model}); 
      this.$el.append(taskView.render().el); 
     }, this); 

     return this; 
    } 
}); 

Изменить шаблон, чтобы использовать новые данные, которые были переданы ему.

// access the model stuff with data.title, etc. 
<script id="recentTasksTemplate" type="text/template"> 
    <div class="task clearfix"> 
     <div class="image"> 
      <img src="<%= data.image %>" /> 
     </div> 
     <div class="details"> 
      <h3 class="title"><%= data.title %></h3> 
      <div class="description"> 
       <%= shortDesc %> 
      </div> 
     </div> 
    <div> 
</script> 

EDIT:

Вид Backbone предназначен для управления DOM элемента, так что это просто хорошая идея, чтобы каждая задача будет своим собственным экземпляром вида. Это облегчает работу по расширению и изменению текста на основе щелчка. Также лучше не иметь код вне представления, изменяющего вещи внутри его элемента DOM, поэтому хорошо делать эту манипуляцию внутри каждого вида задачи.

Это похоже на TodoView в образце Todo:

http://backbonejs.org/docs/todos.html

http://backbonejs.org/examples/todos/index.html

Вы можете передать функции шаблона: любой JavaScript Object (даже объект с функциями, а не только свойства). Поскольку вы хотите отображать некоторые данные, которые не являются технически частью модели, передача объекта data - это просто способ получить материал, который вам нужен, в шаблон.

+0

Это действительно круто. Спасибо @ paul-hoenecke. Отлично работает и, кажется, хорошо работает. Мне было интересно, если бы вы могли более подробно пояснить 2 конкретных момента: 1. «создать представление для каждой задачи» (в разделе «RecentTaskView») 2. «визуализировать» часть (под TaskView). Я не знал, что могу передать несколько атрибутов модели на «this.template» – John

+0

Я редактировал свой оригинальный вопрос одним последним вопросом @ paul-hoenecke. Мой код действительно работает, но это больше подходит для лучшей практики. Еще раз спасибо. – John

+0

Выглядит хорошо. –

Смежные вопросы