jQuery CSS плагин, который возвращает вычисленный стиль элемента для псевдо клонирования этого элемента? - PullRequest
67 голосов
/ 17 июня 2009

Я ищу способ использования jQuery для возврата объекта вычисленных стилей для 1-го сопоставленного элемента. Затем я мог бы передать этот объект другому вызову метода jQuery css.

Например, с width , я могу сделать следующее, чтобы 2 div имели одинаковую ширину:

$('#div2').width($('#div1').width());

Было бы неплохо, если бы я мог сделать ввод текста похожим на существующий диапазон :

$('#input1').css($('#span1').css());

где .css () без аргумента возвращает объект, который можно передать .css (obj) .

(Я не могу найти плагин jQuery для этого, но похоже, что он должен существовать. Если его не существует, я превращу свой плагин ниже в плагин и опубликую его со всеми свойствами, которые я использую. )

В принципе, я хочу псевдоклонировать определенные элементы , но использовать другой тег . Например, у меня есть элемент li, который я хочу скрыть и поместить поверх него элемент ввода, который выглядит одинаково. Когда пользователь вводит , похоже, что он редактирует встроенный элемент .

Я также открыт для других подходов к этой проблеме псевдоклонирования для редактирования. Есть предложения?

Вот что у меня сейчас есть. Единственная проблема - просто получить все возможные стили. Это может быть смехотворно длинный список.


jQuery.fn.css2 = jQuery.fn.css;
jQuery.fn.css = function() {
    if (arguments.length) return jQuery.fn.css2.apply(this, arguments);
    var attr = ['font-family','font-size','font-weight','font-style','color',
    'text-transform','text-decoration','letter-spacing','word-spacing',
    'line-height','text-align','vertical-align','direction','background-color',
    'background-image','background-repeat','background-position',
    'background-attachment','opacity','width','height','top','right','bottom',
    'left','margin-top','margin-right','margin-bottom','margin-left',
    'padding-top','padding-right','padding-bottom','padding-left',
    'border-top-width','border-right-width','border-bottom-width',
    'border-left-width','border-top-color','border-right-color',
    'border-bottom-color','border-left-color','border-top-style',
    'border-right-style','border-bottom-style','border-left-style','position',
    'display','visibility','z-index','overflow-x','overflow-y','white-space',
    'clip','float','clear','cursor','list-style-image','list-style-position',
    'list-style-type','marker-offset'];
    var len = attr.length, obj = {};
    for (var i = 0; i < len; i++) 
        obj[attr[i]] = jQuery.fn.css2.call(this, attr[i]);
    return obj;
}

Редактировать: Я уже некоторое время использую код выше. Он работает хорошо и ведет себя точно так же, как оригинальный метод css, с одним исключением: если передано 0 аргументов, он возвращает вычисленный объект стиля.

Как видите, он немедленно вызывает оригинальный метод css, если это применимо. В противном случае он получает вычисленные стили всех перечисленных свойств (собранные из списка вычисленных стилей Firebug). Хотя он получает длинный список значений, он довольно быстрый. Надеюсь, что это полезно для других.

Ответы [ 9 ]

59 голосов
/ 20 июня 2011

Два года спустя, но у меня есть решение, которое вы ищете. Вот плагин, который я написал (оборачивая функцию другого парня в формат плагина), который делает именно то, что вы хотите, но получает все возможные стили во всех браузерах, даже IE.

jquery.getStyleObject.js:

/*
 * getStyleObject Plugin for jQuery JavaScript Library
 * From: http://upshots.org/?p=112
 *
 * Copyright: Unknown, see source link
 * Plugin version by Dakota Schneider (http://hackthetruth.org)
 */

(function($){
    $.fn.getStyleObject = function(){
        var dom = this.get(0);
        var style;
        var returns = {};
        if(window.getComputedStyle){
            var camelize = function(a,b){
                return b.toUpperCase();
            }
            style = window.getComputedStyle(dom, null);
            for(var i=0;i<style.length;i++){
                var prop = style[i];
                var camel = prop.replace(/\-([a-z])/g, camelize);
                var val = style.getPropertyValue(prop);
                returns[camel] = val;
            }
            return returns;
        }
        if(dom.currentStyle){
            style = dom.currentStyle;
            for(var prop in style){
                returns[prop] = style[prop];
            }
            return returns;
        }
        return this.css();
    }
})(jQuery);

Основное использование довольно просто:

var style = $("#original").getStyleObject(); // copy all computed CSS properties
$("#original").clone() // clone the object
    .parent() // select it's parent
    .appendTo() // append the cloned object to the parent, after the original
                // (though this could really be anywhere and ought to be somewhere
                // else to show that the styles aren't just inherited again
    .css(style); // apply cloned styles

Надеюсь, это поможет.

22 голосов
/ 20 июня 2009

Это не jQuery, но в Firefox, Opera и Safari вы можете использовать window.getComputedStyle(element), чтобы получить вычисленные стили для элемента, а в IE <= 8 вы можете использовать <code>element.currentStyle. Возвращаемые объекты различны в каждом случае, и я не уверен, насколько хорошо они будут работать с элементами и стилями, созданными с помощью Javascript, но, возможно, они будут полезны.

В Safari вы можете делать следующее, что выглядит довольно аккуратно:

document.getElementById('b').style.cssText = window.getComputedStyle(document.getElementById('a')).cssText;
5 голосов
/ 28 января 2010

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

После размышлений о том, как "клонировать" или "скопировать" стили элементов из одного в другой, я пришел к выводу, что не слишком оптимальным является подход циклически проходить через n и применять к n2, но мы уже застрял с этим.

Когда вы сталкиваетесь с этими проблемами, вам редко когда-либо приходится копировать ВСЕ стили из одного элемента в другой ... У вас обычно есть особая причина хотеть применить "некоторые" стили.

Вот то, к чему я вернулся:

$.fn.copyCSS = function( style, toNode ){
  var self = $(this);
  if( !$.isArray( style ) ) style=style.split(' ');
  $.each( style, function( i, name ){ toNode.css( name, self.css(name) ) } );
  return self;
}

Вы можете передать ему разделенный пробелами список атрибутов css в качестве первого аргумента и узел, к которому вы хотите их клонировать, в качестве второго аргумента, например:

$('div#copyFrom').copyCSS('width height color',$('div#copyTo'));

После всего, что кажется «смещенным» после этого, я постараюсь исправить с помощью таблиц стилей, чтобы не загромождать мои J слишком большим количеством пропущенных идей.

4 голосов
/ 21 июня 2009

Теперь, когда у меня было некоторое время, чтобы разобраться в проблеме и лучше понять, как работает внутренний метод css в jQuery, то, что я разместил, кажется, работает достаточно хорошо для случая использования, который я упомянул.

Было предложено решить эту проблему с помощью CSS, но я думаю, что это более обобщенное решение, которое будет работать в любом случае без необходимости добавлять классы удаления или обновлять свой CSS.

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

3 голосов
/ 20 июня 2013

Многоцелевой .css()

Использование

$('body').css();        // -> { ... } - returns all styles
$('body').css('*');     // -> { ... } - the same (more verbose)
$('body').css('color width height')  // -> { color: .., width: .., height: .. } - returns requested styles
$('div').css('width height', '100%')  // set width and color to 100%, returns self
$('body').css('color')  // -> '#000' - native behaviour

Код

(function($) {

    // Monkey-patching original .css() method
    var nativeCss = $.fn.css;

    var camelCase = $.camelCase || function(str) {
        return str.replace(/\-([a-z])/g, function($0, $1) { return $1.toUpperCase(); });
    };

    $.fn.css = function(name, value) {
        if (name == null || name === '*') {
            var elem = this.get(0), css, returns = {};
            if (window.getComputedStyle) {
                css = window.getComputedStyle(elem, null);
                for (var i = 0, l = css.length; i < l; i++) {
                    returns[camelCase(css[i])] = css.getPropertyValue(css[i]);
                }
                return returns;
            } else if (elem.currentStyle) {
                css = elem.currentStyle;
                for (var prop in css) {
                    returns[prop] = css[prop];
                }
            }
            return returns;
        } else if (~name.indexOf(' ')) {
            var names = name.split(/ +/);
            var css = {};
            for (var i = 0, l = names.length; i < l; i++) {
                css[names[i]] = nativeCss.call(this, names[i], value);
            }
            return arguments.length > 1 ? this : css;
        } else {
            return nativeCss.apply(this, arguments);
        }
    }

})(jQuery);

Основная идея взята из ответов Дакоты & HexInteractive .

3 голосов
/ 07 октября 2010

Мне нравится ваш ответ Quickredfox. Мне нужно было скопировать немного CSS, но не сразу, поэтому я изменил его, чтобы сделать необязательным toNode.

$.fn.copyCSS = function( style, toNode ){
  var self = $(this),
   styleObj = {},
   has_toNode = typeof toNode != 'undefined' ? true: false;
 if( !$.isArray( style ) ) {
  style=style.split(' ');
 }
  $.each( style, function( i, name ){ 
  if(has_toNode) {
   toNode.css( name, self.css(name) );
  } else {
   styleObj[name] = self.css(name);
  }  
 });
  return ( has_toNode ? self : styleObj );
}

Если вы называете это так:

$('div#copyFrom').copyCSS('width height color');

Затем он вернет объект с вашими CSS-объявлениями, чтобы вы могли использовать его позже:

{
 'width': '140px',
 'height': '860px',
 'color': 'rgb(238, 238, 238)'
}

Спасибо за отправную точку.

2 голосов
/ 22 января 2014

Я просто хотел добавить расширение к коду, предоставленному Дакотой.

Если вы хотите клонировать элемент со всеми примененными к нему стилями и всеми дочерними элементами, вы можете использовать следующий код:

/*
 * getStyleObject Plugin for jQuery JavaScript Library
 * From: http://upshots.org/?p=112
 *
 * Copyright: Unknown, see source link
 * Plugin version by Dakota Schneider (http://hackthetruth.org)
 */

(function($){
    $.fn.getStyleObject = function(){
        var dom = this.get(0);
        var style;
        var returns = {};
        if(window.getComputedStyle){
            var camelize = function(a,b){
                return b.toUpperCase();
            }
            style = window.getComputedStyle(dom, null);
            for(var i=0;i<style.length;i++){
                var prop = style[i];
                var camel = prop.replace(/\-([a-z])/g, camelize);
                var val = style.getPropertyValue(prop);
                returns[camel] = val;
            }
            return returns;
        }
        if(dom.currentStyle){
            style = dom.currentStyle;
            for(var prop in style){
                returns[prop] = style[prop];
            }
            return returns;
        }
        return this.css();
    }


    $.fn.cloneWithCSS = function() {
        styles = {};

        $this = $(this);
        $clone = $this.clone();
        $clone.css( $this.getStyleObject() );

        children = $this.children().toArray();
        var i = 0;
        while( children.length ) {
            $child = $( children.pop() );
            styles[i++] = $child.getStyleObject();
            $child.children().each(function(i, el) {
                children.push(el);
            })
        }

        cloneChildren = $clone.children().toArray()
        var i = 0;
        while( cloneChildren.length ) {
            $child = $( cloneChildren.pop() );
            $child.css( styles[i++] );
            $child.children().each(function(i, el) {
                cloneChildren.push(el);
            })
        }

        return $clone
    }

})(jQuery);

Тогда вы можете просто сделать: $clone = $("#target").cloneWithCSS()

2 голосов
/ 18 февраля 2012

Отличная функция, предоставляемая ОП. Я немного изменил его, чтобы вы могли выбирать, какие значения вы хотите вернуть.

(function ($) {
    var jQuery_css = $.fn.css,
        gAttr = ['font-family','font-size','font-weight','font-style','color','text-transform','text-decoration','letter-spacing','word-spacing','line-height','text-align','vertical-align','direction','background-color','background-image','background-repeat','background-position','background-attachment','opacity','width','height','top','right','bottom','left','margin-top','margin-right','margin-bottom','margin-left','padding-top','padding-right','padding-bottom','padding-left','border-top-width','border-right-width','border-bottom-width','border-left-width','border-top-color','border-right-color','border-bottom-color','border-left-color','border-top-style','border-right-style','border-bottom-style','border-left-style','position','display','visibility','z-index','overflow-x','overflow-y','white-space','clip','float','clear','cursor','list-style-image','list-style-position','list-style-type','marker-offset'];
    $.fn.css = function() {
        if (arguments.length && !$.isArray(arguments[0])) return jQuery_css.apply(this, arguments);
        var attr = arguments[0] || gAttr,
            len = attr.length,
            obj = {};
        for (var i = 0; i < len; i++) obj[attr[i]] = jQuery_css.call(this, attr[i]);
        return obj;
    }
})(jQuery);

Выберите, какие значения вы хотите, указав свой собственный массив: $().css(['width','height']);

0 голосов
/ 02 ноября 2010
$.fn.cssCopy=function(element,styles){
var self=$(this);
if(element instanceof $){
    if(styles instanceof Array){
        $.each(styles,function(val){
            self.css(val,element.css(val));
        });
    }else if(typeof styles===”string”){
        self.css(styles,element.css(styles));
    }
}
return this;
};

Пример использования

$("#element").cssCopy($("#element2"),['width','height','border'])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...