2016-12-23 1 views
6

Manchmal bin ich gezwungen, CSS-Stile programmgesteuert zum DOM hinzufügen (wenn Sie einen Grund brauchen: Stellen Sie sich vor, ein kleines Ui Widget, das mit einem eigenen Styling kommt aber nur aus einem bestehen soll einzelne * .js Datei für leichtere Handhabung). In diesem Fall bevorzuge ich die Definition des Stils in meinem Skriptcode mit Objektnotation anstelle einer großen Zeichenfolge, die Regeln, Eigenschaften und Markup mischt.Konvertieren CSS-Objekt in Style-Tag

var thumbHoverStyle = { 
    "background-color": "rgba(211, 211, 211, 0.5)", 
    "cursor": "pointer" 
}; 

gegen

var thumbHoverStyle = "<style> .thumb:hover { background-color: rgba(211, 211, 211, 0.5); cursor: pointer; } </style>"; 

Eine solche CSS-Objekt kann leicht mit JQuery's .css() function verwendet werden, aber der Ärger beginnt, sobald ich einen css pseudo-class stylen möchte (in meinem Beispiel: Hover). In diesem Fall kann ich die JQuery-Funktion .css() nicht verwenden und ich falle zurück, um ein entsprechendes style-Tag in mein DOM einzufügen.

var thumbHoverStyleTag = toStyleTag({ ".thumb:hover": thumbHoverStyle }); 
_root.append(thumbHoverStyleTag); 

ich gegoogelt und stackoverflowed konnte aber nicht eine Nutzenfunktion finden, die mein CSS-Objekt in einen Stil-Tag konvertiert. Am Ende schrieb ich meine eigene Funktion (und ich werde es wahrscheinlich als Antwort auf diese Frage bereitstellen), aber ich möchte immer noch wissen, ob es eine Bibliotheksfunktion dafür gibt. Was ist die eleganteste Methode, dies zu erreichen?

bearbeiten

Meine Implementierung in Typoskript:

function appendPxIfNumber(value: any): string 
{ 
    return (typeof value === "number") ? "" + value + "px" : value; 
} 

function toStyleTag(rulesObj: any) 
{ 
    var combinedRules: string = ""; 
    for (var selector in rulesObj) 
    { 
     var cssObject = rulesObj[selector]; 
     var combinedProperties = ""; 
     for (var prop in cssObject) { 
      var value = cssObject[prop]; 
      combinedProperties += `${prop}: ${appendPxIfNumber(value)};` + "\n"; 
     } 
     combinedRules += ` ${selector} {${combinedProperties}}` + "\n"; 
    } 
    return $(`<style>${combinedRules}</style>`); 
} 

Anwendungsbeispiel:

var styleTag = toStyleTag({ ".thumb": thumbStyle, ".thumb:hover": thumbHoverStyle }); 

Antwort

2

Hier ist ein funktionierendes Beispiel, die mit dem Ursprung Stilobjekt funktioniert: Ich werde konvertieren die JSON in CSS. und definiere ein Ziel, das gestylt werden sollte Denk daran, dass es keinen Selektor gibt, der gestylt werden sollte ... Also fügte ich einen targetSelector hinzu.

var targetSelector='.thumb:hover', 
    styleObj = { 
     "background-color": "rgba(211, 211, 211, 0.5)", 
     "cursor": "pointer" 
    }, 

    // Convert the JSON into CSS 
    styleTagContent = JSON.stringify(styleObj,null,'\t') 
          .replace(/"/g,'') 
          .replace(/,\n/g,';') 
          .replace(/\}/g, ';}') 



    $('<style>'+targetSelector+styleTagContent+'</style>').appendTo('head'); 

Hier ist ein Plunk arbeiten, um zu sehen, wie es funktioniert.

+0

Oh schön, ich habe nicht daran gedacht, mit 'JSON stringify' mein CSS-Objekt in einen CSS-String zu konvertieren. – Martin

0

möchte ich versucht sein:

  • fügen Sie ein thumbHoverStyle CSS Objekt auf mouseover(); und
  • ersetzen Sie es mit einem thumbDefaultStyle CSS Objekt auf mouseout()

var thumbStyle = { 
 
    "width" : "100px", 
 
    "height" : "100px", 
 
    "text-align" : "center", 
 
    "line-height" : "100px", 
 
    "background-color": "rgb(211, 211, 211)" 
 
}; 
 

 
var thumbHoverStyle = { 
 
    "color" : "rgb(255,255,255)", 
 
    "background-color": "rgb(255, 0, 0)", 
 
    "cursor": "pointer" 
 
}; 
 

 
var thumbDefaultStyle = { 
 
    "color" : "rgb(0,0,0)", 
 
    "background-color": "rgb(211, 211, 211)", 
 
    "cursor": "default" 
 
}; 
 

 
$(document).ready(function(){ 
 

 
    $('div').css(thumbStyle); 
 

 
    $('input[type="checkbox"]').change(function(){ 
 

 
     if ($('input[type="checkbox"]').prop('checked')) { 
 

 
      $('div').mouseover(function(){ 
 
       $(this).css(thumbHoverStyle); 
 
      }); 
 

 
      $('div').mouseout(function(){ 
 
       $(this).css(thumbDefaultStyle); 
 
      }); 
 
     } 
 

 
     else { 
 

 
      $('div').mouseover(function(){ 
 
       $(this).css(thumbDefaultStyle); 
 
      }); 
 

 
      $('div').mouseout(function(){ 
 
       $(this).css(thumbDefaultStyle); 
 
      }); 
 
     } 
 
    }); 
 
});
div, button { 
 
display: inline-block; 
 
margin-right: 24px; 
 
vertical-align: top; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<div>Hover Me</div> 
 
<input type="checkbox" />Activate New Hover Behaviour

+1

Vielen Dank für Ihre vorgeschlagene Lösung. Aber ich habe zusätzliche Gründe, die in meiner Frage beschriebene Konverterfunktion zu finden. Die Klasse: hover war nur ein Beispiel. Und ich würde lieber die Rendering-Engine des Browsers mit den Hover-visuellen Zuständen von Elementen umgehen lassen, als den Maus-In/mouseOut-Handler-Code zu schreiben, um css: hover zu simulieren. – Martin

1

Die Methodik hinter meiner Funktion toStyleTag() ist, dass es erste Iteration über styleTag ein for...in statement verwenden und prüfen, ob styleTaghasOwnProperty() von die selector. I dann reduce() das Array durch Ausführen Object.keys() auf das Objekt zurückgegeben, styleTag[selector], die ich die accumulatorconcat() durch die currentValue (die Eigenschaft) und die Füge styleTag[selector][currentValue]] (die Regel) seine : getrennt.Wenn Sie dies tun, wird styles zu einem Array von Strings, die die Form property: rule haben. Dies ist jetzt das Format, das wir verwenden müssen, insertRule(), mit dem wir die neue CSS-Regel in das aktuelle Stylesheet einfügen. Beachten Sie, dass ich die Länge des cssRules packe, um den Index + 1 zu finden, sodass wir diese neue Regel ganz am Ende unseres Stylesheets einfügen können, um sicherzustellen, dass sie nicht überschrieben wird.

var styleSheet = document.styleSheets[0]; 
 

 
function toStyleTag(styleTag) { 
 
    for(var selector in styleTag) { 
 
    if(styleTag.hasOwnProperty(selector)) { 
 
     let styles = Object.keys(styleTag[selector]).reduce(function(accumulator, currentValue) { 
 
     return accumulator.concat([currentValue, styleTag[selector][currentValue]].join(':')); 
 
     }, []); 
 
     styleSheet.insertRule(selector + '{' + styles.join(';') + '}', styleSheet.cssRules.length); 
 
    } 
 
    } 
 
} 
 

 
var thumbHoverStyle = { 
 
    'background-color': 'rgba(211, 211, 211, 0.5)', 
 
    'cursor': 'pointer' 
 
}; 
 

 
toStyleTag({ '.thumb:hover': thumbHoverStyle });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div class="thumb"> 
 
    <img src="http://placehold.it/350x350"> 
 
</div>

+0

Schön. Meine 'toStyleTag()' -Funktion ist ähnlich, Iterieren über die Eingabe mit einer 'for..in'-Schleife und verketten die Teile einzeln. – Martin

0

Ich wollte eine andere auf diesem gehen haben, denn es ist ein faszinierendes Problem.

Hier ist die native Javascript Lösung, die ich zusammen:

var thumbStyle = { 
 
    "width" : "100px", 
 
    "height" : "100px", 
 
    "text-align" : "center", 
 
    "line-height" : "100px", 
 
    "background-color": "rgb(211, 211, 211)" 
 
}; 
 

 
var thumbHoverStyle = { 
 
    "color" : "rgb(255,255,255)", 
 
    "background-color": "rgb(255, 0, 0)", 
 
    "cursor": "pointer" 
 
}; 
 

 
var dynamicStyle = document.createElement('style'); 
 
document.head.appendChild(dynamicStyle); 
 
var dynamicStyleSheet = dynamicStyle.sheet; 
 

 
function addStyles(selector, cssStyleObject) { 
 
    var properties = Object.keys(cssStyleObject); 
 
    properties.forEach(function(property){ 
 
     var value = cssStyleObject[property]; 
 
     
 
     var dynamicRule = selector + ' {' + property + ': ' + value + ';}'; 
 
     
 
     dynamicStyleSheet.insertRule(dynamicRule, dynamicStyleSheet.cssRules.length); 
 
    }); 
 
} 
 

 
// Add styles dynamically by stating a selector and the name of a CSS Style Object 
 

 
addStyles('div', thumbStyle); 
 
addStyles('div:hover', thumbHoverStyle);
<div>Hover Me</div>

+0

Nicht sicher, ob es wirklich wichtig ist, aber auf diese Weise würden Sie eine neue Regel für jede Eigenschaft, die Teil des Stils ist, erzeugen und hinzufügen, anstatt eine Regel mit n Eigenschaften. – Martin

+0

Ich bin mir nicht sicher, ob ich folge - kannst du es bitte nochmal erklären? Vielen Dank. – Rounin

+0

Soweit ich verstehe, würde Ihr resultierendes CSS wie folgt aussehen: '.foo {color: red;} .foo {background-color: weiß;} .foo {margin-left: 2px;} .foo {margin-right: 4px ;} 'statt' .foo {Farbe: rot; Hintergrundfarbe: weiß; Rand links: 2px; Rand rechts: 4px;} ' – Martin