/
css_style_sheet.js
201 lines (169 loc) · 5.48 KB
/
css_style_sheet.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// ==========================================================================
// Project: SproutCore - JavaScript Application Framework
// Copyright: ©2006-2010 Sprout Systems, Inc. and contributors.
// Portions ©2008-2010 Apple Inc. All rights reserved.
// License: Licensed under MIT license (see license.js)
// ==========================================================================
sc_require('css/css_rule') ;
/**
@class SC.CSSStyleSheet
A style sheet object wraps a document style sheet object. SC.CSSStyleSheet will
re-use stylesheet objects as needed.
@extends SC.Object
*/
SC.CSSStyleSheet = SC.Object.extend(
/** @scope SC.CSSStyleSheet.prototype */ {
init: function() {
sc_super() ;
var ss = this.styleSheet ;
if (!ss) {
// create the stylesheet object the hard way (works everywhere)
ss = this.styleSheet = document.createElement('style') ;
ss.type = 'text/css' ;
var head = document.getElementsByTagName('head')[0] ;
if (!head) head = document.documentElement ; // fix for Opera
head.appendChild(ss) ;
}
// cache this object for later
var ssObjects = this.constructor.styleSheets ;
if (!ssObjects) ssObjects = this.constructor.styleSheets = {} ;
ssObjects[SC.guidFor(ss)] ;
// create rules array
var rules = ss.rules || SC.EMPTY_ARRAY ;
var array = SC.SparseArray.create(rules.length) ;
array.delegate = this ;
this.rules = array ;
return this ;
},
/**
@property {Boolean} YES if the stylsheet is enabled.
*/
isEnabled: function(key, val) {
if (val !== undefined) {
this.styleSheet.disabled = !val ;
}
return !this.styleSheet.disabled ;
}.property(),
isEnabledBindingDefault: SC.Binding.bool(),
/**
DO NOT MODIFY THIS OBJECT DIRECTLY!!!! Use the methods defined on this
object to update properties of the style sheet; otherwise, your changes
will not be reflected.
@property {CSSStyleSheet} RO
*/
styleSheet: null,
/**
@property {String}
*/
href: function(key, val) {
if (val !== undefined) {
this.styleSheet.href = val ;
}
else return this.styleSheet.href ;
}.property(),
/**
@property {String}
*/
title: function(key, val) {
if (val !== undefined) {
this.styleSheet.title = val ;
}
else return this.styleSheet.title ;
}.property(),
/**
@property {SC.Array} contains SC.CSSRule objects
*/
rules: null,
/**
You can also insert and remove rules on the rules property array.
*/
insertRule: function(rule) {
var rules = this.get('rules') ;
},
/**
You can also insert and remove rules on the rules property array.
*/
deleteRule: function(rule) {
var rules = this.get('rules') ;
rules.removeObject(rule) ;
},
// TODO: implement a destroy method
/**
@private
Invoked by the sparse array whenever it needs a particular index
provided. Provide the content for the index.
*/
sparseArrayDidRequestIndex: function(array, idx) {
// sc_assert(this.rules === array) ;
var rules = this.styleSheet.rules || SC.EMPTY_ARRAY ;
var rule = rules[idx] ;
if (rule) {
array.provideContentAtIndex(idx, SC.CSSRule.create({
rule: rule,
styleSheet: this
}));
}
},
/** @private synchronize the browser's rules array with our own */
sparseArrayDidReplace: function(array, idx, amt, objects) {
var cssRules = objects.collect(function(obj) { return obj.rule; }) ;
this.styleSheet.rules.replace(idx, amt, cssRules) ;
}
});
SC.mixin(SC.CSSStyleSheet,
/** SC.CSSStyleSheet */{
/**
Find a stylesheet object by name or href. If by name, .css will be
appended automatically.
{{{
var ss = SC.CSSStyleSheet.find('style.css') ;
var ss2 = SC.CSSStyleSheet.find('style') ; // same thing
sc_assert(ss === ss2) ; // SC.CSSStyleSheet objects are stable
}}}
@param {String} nameOrUrl a stylsheet name or href to find
@returns {SC.CSSStyleSheet} null if not found
*/
find: function(nameOrUrl) {
var isUrl = nameOrUrl ? nameOrUrl.indexOf('/') >= 0 : NO ;
if (!nameOrUrl) return null ; // no name or url? fail!
if (!isUrl && nameOrUrl.indexOf('.css') == -1) {
nameOrUrl = nameOrUrl + '.css' ;
}
// initialize styleSheet cache
var ssObjects = this.styleSheets ;
if (!ssObjects) ssObjects = this.styleSheets = {} ;
var styleSheets = document.styleSheets ;
var ss, ssName, ssObject, guid ;
for (var idx=0, len=styleSheets.length; idx < len; ++idx) {
ss = styleSheets[idx] ;
if (isUrl) {
if (ss.href === nameOrUrl) {
guid = SC.guidFor(ss) ;
ssObject = ssObjects[guid] ;
if (!ssObject) {
// cache for later
ssObject = ssObjects[guid] = this.create({ styleSheet: ss }) ;
}
return ssObject ;
}
}
else {
if (ssName = ss.href) {
ssName = ssName.split('/') ; // break up URL
ssName = ssName[ssName.length-1] ; // get last component
if (ssName == nameOrUrl) {
guid = SC.guidFor(ss) ;
ssObject = ssObjects[guid] ;
if (!ssObject) {
// cache for later
ssObject = ssObjects[guid] = this.create({ styleSheet: ss }) ;
}
return ssObject ;
}
}
}
}
return null ; // stylesheet not found
},
styleSheets: null
});