2012-09-30 10 views
2

我創建了一個克隆用於快速原型設計的元素的插件。該插件將遍歷元素上具有'data-clone'數據屬性的每個元素,並在該屬性中設置克隆數量。如何控制我的jQuery插件使用.each()進行迭代的順序?

例如:

<table data-clone="3"> 
    <thead> 
     <tr> 
      <th>#</th> 
      <th>Name</th> 
      <th>Project</th> 
     </tr> 
    </thead> 
    <tbody> 
     <tr data-clone="4"> 
      <td>1</td> 
      <td>Steve Sax</td> 
      <td>Something here.</td> 
     </tr> 
    </tbody> 
</table> 

這似乎是第一個元素上正常運行。但是,如果我有一個嵌套的項目,其中的容器克隆,所以裏面的元素。它似乎克隆嵌套的項目,並在第一個外部,但不會將這些嵌套項目克隆到新克隆的外部容器。

我這裏有一個小提琴:Fiddle

它具有插件和調用。如果你點擊「運行」,你應該看到我的意思。但是,我感覺如果.each()方法先從嵌套項目迭代,然後繼續工作,所有克隆都是正確的。

在此先感謝,

亞當。

這裏是插件本身供參考。再一次,所有人都在小提琴中。

/*! Adamin Clone - v0.1.0 - 2012-09-29 
    * https://github.com/pensive612/Adamin-Clone 
    * Copyright (c) 2012 Adam L.; Licensed MIT, GPL */ 

(function(window, document, $, undefined) { 
    var Project = function(elem, options) { 
     this.elem = elem; 
     this.$elem = $(elem); 
     this.options = options; 
     this.metadata = this.$elem.data('clone-cap'); 
}; 

Project.prototype = { 
    defaults: { 
    cloneCap: 100 
    }, 
    init: function() { 
    this.config = $.extend({}, this.defaults, this.options, this.metadata); 

    this.getCloneValue(this.$elem); 

    return this; 
    }, 
    getCloneValue: function(elem) { 
    var configCap = this.config.cloneCap; 
    var cloneValue = elem.data('clone'); 

    // parse data-clone value 
    cloneValue = this.parseCloneValue(cloneValue); 

    // if data-clone value is valid, send to clone function 
    if (cloneValue && (cloneValue < configCap)) { 
     this.cloneItem(this.$elem, cloneValue); 

    // otherwise, return false 
    } else { 

     if (cloneValue > configCap) { 
     window.console.log('Your data-clone value is too high for the defaults. Please check documentation to override cap in config.'); 
     } 

     return false; 
    } 
    }, 
    parseCloneValue: function(value) { 
    var cloneValue = parseInt(value, 10); 
    return cloneValue; 
    }, 
    cloneItem: function(elem, value) { 
    var elemClone; 

    for (var i = value; i > 0; i--) { 
     elemClone = elem.clone(true); 
     elemClone.removeAttr('data-clone'); 
     elemClone.addClass('clone-' + i); 
     elemClone.insertAfter(elem); 
    } 
    } 
}; 

Project.defaults = Project.prototype.defaults; 

$.fn.adaminClone = function(options, callback) { 

    if (typeof callback === 'function') { 
    callback.call(this); 
    } 

    return this.each(function() { 
    new Project(this, options).init(); 
    }); 
}; 

window.Project = Project; 

}(window, document, jQuery)); 

回答

0

ComputerArts做了一個很棒的重寫函數的工作。不過,我可以只修改,以保持插件模式和可擴展性:

return this.each(function() { 
    new Project(this, options).init(); 
}); 

要這樣:

return this.sort(function(a, b) { 
    var va = $(a).parents('[data-clone]').length; 
    var vb = $(b).parents('[data-clone]').length; 
    return vb - va; 
    }).each(function() { 
     new Project(this, options).init(); 
    }); 

使用父母()的長度是測量深度的好方法。感謝ComputerArts和Shoky讓我獲得需要的地方。

0

好的,所以我給你找了點東西。

Check this simplified fiddle

基本上你開始從最深的元素克隆和去向上。 評論在代碼中。

var elements = $.find('[data-clone]'); //get all the elements that need to be cloned 
var elementsData = []; //will store and sort the elements 

//store the elements with their depth 
$.each(elements, function(i, element) { 

    var obj = {}; 
    obj.element = $(element); 
    obj.depth = $(element).parents().length; 

    elementsData.push(obj); 

    // This can be optimized, it's just easier to understand the code. 
    // Alternatively use 
    // elementsData.push({ element : $(element), depth : $(element).parents().length }); 
}) 

//sort them by deepest element 
elementsData.sort(SortByDepth); 


$.each(elementsData, function(i, elementData) { 
    var element = elementData.element; 

    //clone ot the number of times wanted. 
    for (var c = 0; c < element.attr('data-clone'); c++) { 
     element 
      .clone(true) 
      .removeAttr('data-clone') 
      .addClass('clone-' + c). 
      insertAfter(element); 
    } 
}) 

//function that sorts the elements; 
function SortByDepth(a, b){ 
    var aDepth = a.depth; 
    var bDepth = b.depth; 
    return ((aDepth > bDepth) ? -1 : ((aDepth < bDepth) ? 1 : 0)); 
} 

注:在數據克隆= 4,該腳本將克隆它的4倍,所以你必須在屏幕上一共有5(因爲一個已經存在)。它你想正好4,在for循環突出放

for (var c = 0; c < parseInt(element.attr('data-clone') - 1); c++) { 
+0

哇,電腦藝術。非常感謝您爲此付出的時間。我完全看到你要去的地方。我做了一些類似的事情(在一個黑客的幫助下),它保留了它的插件模式,並且仍然很快完成了這項工作。 – Adam

+0

不客氣。我真的一行一行,真的很簡單,以便即使是JavaScript的新用戶也能理解。我告訴自己,你似乎知道js,所以你可以優化它。 –

相關問題