zurb / orbit

454 stars 96 forks source link

Populated by Ember.js slides are surrounded with <script> tag #134

Open Uladzimiro opened 11 years ago

Uladzimiro commented 11 years ago
NOTICE: Initially I posted this issue here, but later realized that it is not the best place to open this issue so I opened the same issue in zurb/founcation project. I do not have an ability to delete it here, so sorry in advance. However, this issue might be relevant to this project too.

I use Ember.js to populate Orbit's content. I.e. by iterating across all available slides I create li and its img content. However, Ember uses script tags (which do not affect how HTML is displayed) to implement its binding system.

For instance we can come up with the following HTML (unnecessary elements are removed) notice script tags before and after li tags:

<div class="orbit-container">
  <ul data-orbit="" class="orbit-slides-container">
    <script id="metamorph-23-start" type="text/x-placeholder"></script>
    <script id="metamorph-21-start" type="text/x-placeholder"></script>
    <li class="active">
      <img src="img1.jpg" data-bindattr-2="2">
    </li>
    <script id="metamorph-21-end" type="text/x-placeholder"></script>
    <script id="metamorph-22-start" type="text/x-placeholder"></script>
    <li>
      <img src="img2.jpg" data-bindattr-3="3">
    </li>
    <script id="metamorph-22-end" type="text/x-placeholder"></script>
    <script id="metamorph-23-end" type="text/x-placeholder"></script>
  </ul>
</div>

Orbit treats all direct childrens of "orbit-slides-container" as slides that should be displayed and as a result in the example it tries to show 8 slides instead of just 2,

If someone have the same problem here is how I solved it:

1) In js/foundation/foundation.orbit.js all occurrences of slides_container.children() replacewith slides_container.children().not('script') so that it selects all direct children that are not script. Here can be added other possible unnecessary tags. In fact I did a little hack by defining jQuery function and used it instead of children().not('script')

//  Add new jQuery function that selects children without Ember's script wrappers. 
    $.fn.extend({ orbit_slides: function() {
      return $(this).children().not('script');
    }});

Next, replace all slides_container.children() with slides_container.orbit_slides() wich is a bit cleaner and can be easier extended (e.g. add another unnecessary tag).

2) In scss/foundation/components/_orbit.scss at around line 134: this code

      &>* {
        position: absolute;
        top: 0;
        width: 100%;
        @if $text-direction == rtl {
          margin-right: 100%;
        }
        @else {
          margin-left: 100%;
        }

        &:first-child {
          @if $text-direction == rtl {
          margin-right: 0%;
          }
          @else {
          margin-left: 0%;
          }
        }

replace with this one:

// change &>* to &>:not(script) to exclude Ember's script wrappers
      &>:not(script) {
        position: absolute;
        top: 0;
        width: 100%;
        @if $text-direction == rtl {
          margin-right: 100%;
        }
        @else {
          margin-left: 100%;
        }

 // change &:first-child to  &:first-of-type to find first non Ember's script wrappers (works only in IE9 +)
        &:first-of-type {
          @if $text-direction == rtl {
          margin-right: 0%;
          }
          @else {
          margin-left: 0%;
          }
        }

I should mention that :first-of-type pseudo class works only in IE9+ browsers. However, I do not know how otherwise target first li tag in css. It certainly can be done in javascript.