web-dev-qa-db-de.com

jQuery CSS-Plugin, das den berechneten Stil des Elements zurückgibt, um dieses Element durch Pseudo zu klonen?

Ich suche nach einer Möglichkeit, mit jQuery ein Objekt berechneter Stile für das 1. übereinstimmende Element zurückzugeben. Ich könnte dieses Objekt dann an einen anderen Aufruf der css-Methode von jQuery übergeben.

Mit width kann ich zum Beispiel Folgendes tun, damit die 2 Divs dieselbe Breite haben:

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

Es wäre schön, wenn ich eine Texteingabe wie einen vorhandenen Bereich aussehen lassen könnte:

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

dabei gibt css () ohne Argument ein Objekt zurück, das an .css (obj) übergeben werden kann.

(Ich kann kein jQuery-Plugin dafür finden, aber es scheint so, als sollte es existieren. Wenn es nicht existiert, verwende ich mein Plugin in ein Plugin und poste es mit allen Eigenschaften, die ich benutze. 

Grundsätzlich möchte ich bestimmte Elemente pseudo klonen, jedoch ein anderes Tag verwenden. Zum Beispiel habe ich ein li-Element, das ich ausblenden und ein Eingabeelement darüber einfügen möchte, das gleich aussieht. Wenn der Benutzer eingibt, sieht es so aus, als würde er das Element inline bearbeiten.

Ich bin auch offen für andere Ansätze für dieses Pseudo-Klonproblem für die Bearbeitung. Irgendwelche Vorschläge?

Hier ist was ich momentan habe. Das einzige Problem ist, alle möglichen Stile zu erhalten. Dies könnte eine lächerlich lange Liste sein.


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;
}

Edit: Ich habe jetzt den Code oben verwendet. Es funktioniert gut und verhält sich mit einer Ausnahme genau wie die ursprüngliche css-Methode: Wenn 0 args übergeben werden, wird das berechnete style-Objekt zurückgegeben. 

Wie Sie sehen, ruft es sofort die ursprüngliche css-Methode auf, wenn dies der Fall ist. Andernfalls werden die berechneten Stile aller aufgelisteten Eigenschaften abgerufen (aus der Liste der berechneten Stile von Firebug). Obwohl es eine lange Liste von Werten gibt, ist es ziemlich schnell. Hoffe, es ist nützlich für andere.

67
Keith Bentrup

Zwei Jahre später, aber ich habe die Lösung, nach der Sie suchen. Hier ist ein Plugin, das ich geschrieben habe (indem es die Funktion eines anderen Mannes im Plugin-Format einwickelt), das genau das tut, was Sie wollen, aber in allen Browsern alle möglichen Stilen erhält, sogar im 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);

Die grundlegende Verwendung ist ziemlich einfach:

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

Hoffentlich hilft das.

59
Dakota

Es ist nicht jQuery, aber in Firefox, Opera und Safari können Sie window.getComputedStyle(element) verwenden, um die berechneten Stile für ein Element abzurufen, und in IE <= 8 können Sie element.currentStyle verwenden. Die zurückgegebenen Objekte sind in jedem Fall unterschiedlich, und ich bin mir nicht sicher, wie gut sie mit Elementen und Stilen arbeiten, die mit Javascript erstellt wurden, aber vielleicht sind sie nützlich.

In Safari können Sie Folgendes tun, was irgendwie nett ist:

document.getElementById('b').style.cssText = window.getComputedStyle(document.getElementById('a')).cssText;
22
Richard M

Ich weiß nicht, ob Sie mit den Antworten, die Sie bisher erhalten haben, zufrieden sind, aber ich war Sie nicht und meine gefällt Ihnen vielleicht auch nicht, aber es kann jemand anderem helfen. 

Nachdem ich darüber nachgedacht hatte, wie man die Stile der Elemente von einem zum anderen "klonen" oder "kopieren" kann, ist mir klar geworden, dass es nicht sehr optimal für einen Ansatz war, n durchzuschleifen und auf n2 anzuwenden .

Wenn Sie sich mit diesen Problemen konfrontiert sehen, müssen Sie selten ALLE Stile von einem Element in ein anderes kopieren ... Sie haben normalerweise einen bestimmten Grund, "einige" Stile anzuwenden.

Hier ist, worauf ich zurückkehrte:

$.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;
}

Sie können eine durch Leerzeichen getrennte Liste von CSS-Attributen als erstes Argument und den Knoten, an den Sie sie klonen möchten, als zweites Argument übergeben.

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

Was auch immer danach scheint, "falsch" zu sein, werde ich versuchen, mit Stylesheets zu korrigieren, um meine Js nicht mit zu vielen fehlzündenden Ideen zu stören.

5
Quickredfox

Nachdem ich nun etwas Zeit hatte, um das Problem zu untersuchen und besser zu verstehen, wie die interne css-Methode von jQuery funktioniert, scheint das, was ich gepostet habe, für den von mir erwähnten Anwendungsfall gut zu funktionieren. 

Es wurde vorgeschlagen, dass Sie dieses Problem mit CSS lösen können, aber ich denke, dass dies eine allgemeinere Lösung ist, die auf jeden Fall funktionieren wird, ohne dass Sie Klassen hinzufügen oder Ihre CSS aktualisieren müssen.

Ich hoffe, andere finden es nützlich. Wenn Sie einen Fehler finden, lass es mich wissen.

4
Keith Bentrup

Ich mag deine Antwort, Quickredfox. Ich musste etwas CSS kopieren, aber nicht sofort. Deshalb habe ich es modifiziert, um den "toNode" optional zu machen.

$.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 );
}

Wenn du es so nennst:

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

Dann wird ein Objekt mit Ihren CSS-Deklarationen zurückgegeben, das Sie später verwenden können:

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

Danke für den Startpunkt.

3
HexInteractive

Mehrzweck .css()

Verwendungszweck

$('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

Code

(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);

Die Hauptidee stammt aus Dakotas & HexInteractive - Antworten.

3
disfated

Tolle Funktion des OP. Ich habe es leicht modifiziert, damit Sie auswählen können, welche Werte Sie zurückgeben möchten.

(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);

Wählen Sie die gewünschten Werte aus, indem Sie Ihr eigenes Array angeben: $().css(['width','height']);

2
Shea

Ich wollte nur eine Erweiterung des von Dakota eingereichten Codes hinzufügen.

Wenn Sie ein Element mit allen angewendeten Stilen und allen untergeordneten Elementen klonen möchten, können Sie den folgenden Code verwenden:

/*
 * 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);

Dann können Sie einfach folgendes tun: $clone = $("#target").cloneWithCSS()

2
Nonconformist
$.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;
};

Verwenden Sie ein Beispiel

$("#element").cssCopy($("#element2"),['width','height','border'])
0
rterrani