保誠-保戶業務員媒合平台
HelenHuang
2022-06-09 9bdb95c9e34cef640534e5e5a1e2225a80442000
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
'use strict';
 
var csstree = require('css-tree'),
    csstools = require('../css-tools');
 
 
var CSSStyleDeclaration = function(node) {
    this.parentNode = node;
 
    this.properties = new Map();
    this.hasSynced = false;
 
    this.styleAttr = null;
    this.styleValue = null;
 
    this.parseError = false;
};
 
/**
 * Performs a deep clone of this object.
 *
 * @param parentNode the parentNode to assign to the cloned result
 */
CSSStyleDeclaration.prototype.clone = function(parentNode) {
    var node = this;
    var nodeData = {};
 
    Object.keys(node).forEach(function(key) {
        if (key !== 'parentNode') {
            nodeData[key] = node[key];
        }
    });
 
    // Deep-clone node data.
    nodeData = JSON.parse(JSON.stringify(nodeData));
 
    var clone = new CSSStyleDeclaration(parentNode);
    Object.assign(clone, nodeData);
    return clone;
};
 
CSSStyleDeclaration.prototype.hasStyle = function() {
    this.addStyleHandler();
};
 
 
 
 
// attr.style
 
CSSStyleDeclaration.prototype.addStyleHandler = function() {
 
    this.styleAttr = { // empty style attr
        'name': 'style',
        'value': null
    };
 
    Object.defineProperty(this.parentNode.attrs, 'style', {
        get: this.getStyleAttr.bind(this),
        set: this.setStyleAttr.bind(this),
        enumerable: true,
        configurable: true
    });
 
    this.addStyleValueHandler();
};
 
// attr.style.value
 
CSSStyleDeclaration.prototype.addStyleValueHandler = function() {
 
    Object.defineProperty(this.styleAttr, 'value', {
        get: this.getStyleValue.bind(this),
        set: this.setStyleValue.bind(this),
        enumerable: true,
        configurable: true
    });
};
 
CSSStyleDeclaration.prototype.getStyleAttr = function() {
    return this.styleAttr;
};
 
CSSStyleDeclaration.prototype.setStyleAttr = function(newStyleAttr) {
    this.setStyleValue(newStyleAttr.value); // must before applying value handler!
 
    this.styleAttr = newStyleAttr;
    this.addStyleValueHandler();
    this.hasSynced = false; // raw css changed
};
 
CSSStyleDeclaration.prototype.getStyleValue = function() {
    return this.getCssText();
};
 
CSSStyleDeclaration.prototype.setStyleValue = function(newValue) {
    this.properties.clear(); // reset all existing properties
    this.styleValue = newValue;
    this.hasSynced = false; // raw css changed
};
 
 
 
 
CSSStyleDeclaration.prototype._loadCssText = function() {
    if (this.hasSynced) {
        return;
    }
    this.hasSynced = true; // must be set here to prevent loop in setProperty(...)
 
    if (!this.styleValue || this.styleValue.length === 0) {
        return;
    }
    var inlineCssStr = this.styleValue;
 
    var declarations = {};
    try {
        declarations = csstree.parse(inlineCssStr, {
            context: 'declarationList',
            parseValue: false
        });
    } catch (parseError) {
        this.parseError = parseError;
        return;
    }
    this.parseError = false;
 
    var self = this;
    declarations.children.each(function(declaration) {
        try {
          var styleDeclaration = csstools.csstreeToStyleDeclaration(declaration);
          self.setProperty(styleDeclaration.name, styleDeclaration.value, styleDeclaration.priority);
        } catch(styleError) {
            if(styleError.message !== 'Unknown node type: undefined') {
                self.parseError = styleError;
            }
        }
    });
};
 
 
// only reads from properties
 
/**
 * Get the textual representation of the declaration block (equivalent to .cssText attribute).
 *
 * @return {String} Textual representation of the declaration block (empty string for no properties)
 */
CSSStyleDeclaration.prototype.getCssText = function() {
    var properties = this.getProperties();
 
    if (this.parseError) {
        // in case of a parse error, pass through original styles
        return this.styleValue;
    }
 
    var cssText = [];
    properties.forEach(function(property, propertyName) {
        var strImportant = property.priority === 'important' ? '!important' : '';
        cssText.push(propertyName.trim() + ':' + property.value.trim() + strImportant);
    });
    return cssText.join(';');
};
 
CSSStyleDeclaration.prototype._handleParseError = function() {
    if (this.parseError) {
        console.warn('Warning: Parse error when parsing inline styles, style properties of this element cannot be used. The raw styles can still be get/set using .attr(\'style\').value. Error details: ' + this.parseError);
    }
};
 
 
CSSStyleDeclaration.prototype._getProperty = function(propertyName) {
    if(typeof propertyName === 'undefined') {
        throw Error('1 argument required, but only 0 present.');
    }
 
    var properties = this.getProperties();
    this._handleParseError();
 
    var property = properties.get(propertyName.trim());
    return property;
};
 
/**
 * Return the optional priority, "important".
 *
 * @param {String} propertyName representing the property name to be checked.
 * @return {String} priority that represents the priority (e.g. "important") if one exists. If none exists, returns the empty string.
 */
CSSStyleDeclaration.prototype.getPropertyPriority = function(propertyName) {
    var property = this._getProperty(propertyName);
    return property ? property.priority : '';
};
 
/**
 * Return the property value given a property name.
 *
 * @param {String} propertyName representing the property name to be checked.
 * @return {String} value containing the value of the property. If not set, returns the empty string.
 */
CSSStyleDeclaration.prototype.getPropertyValue = function(propertyName) {
    var property = this._getProperty(propertyName);
    return property ? property.value : null;
};
 
/**
 * Return a property name.
 *
 * @param {Number} index of the node to be fetched. The index is zero-based.
 * @return {String} propertyName that is the name of the CSS property at the specified index.
 */
CSSStyleDeclaration.prototype.item = function(index) {
    if(typeof index === 'undefined') {
        throw Error('1 argument required, but only 0 present.');
    }
 
    var properties = this.getProperties();
    this._handleParseError();
 
    return Array.from(properties.keys())[index];
};
 
/**
 * Return all properties of the node.
 *
 * @return {Map} properties that is a Map with propertyName as key and property (propertyValue + propertyPriority) as value.
 */
CSSStyleDeclaration.prototype.getProperties = function() {
    this._loadCssText();
    return this.properties;
};
 
 
// writes to properties
 
/**
 * Remove a property from the CSS declaration block.
 *
 * @param {String} propertyName representing the property name to be removed.
 * @return {String} oldValue equal to the value of the CSS property before it was removed.
 */
CSSStyleDeclaration.prototype.removeProperty = function(propertyName) {
    if(typeof propertyName === 'undefined') {
        throw Error('1 argument required, but only 0 present.');
    }
 
    this.hasStyle();
 
    var properties = this.getProperties();
    this._handleParseError();
 
    var oldValue = this.getPropertyValue(propertyName);
    properties.delete(propertyName.trim());
    return oldValue;
};
 
/**
 * Modify an existing CSS property or creates a new CSS property in the declaration block.
 *
 * @param {String} propertyName representing the CSS property name to be modified.
 * @param {String} [value] containing the new property value. If not specified, treated as the empty string. value must not contain "!important" -- that should be set using the priority parameter.
 * @param {String} [priority] allowing the "important" CSS priority to be set. If not specified, treated as the empty string.
 * @return {undefined}
 */
CSSStyleDeclaration.prototype.setProperty = function(propertyName, value, priority) {
    if(typeof propertyName === 'undefined') {
        throw Error('propertyName argument required, but only not present.');
    }
 
    this.hasStyle();
 
    var properties = this.getProperties();
    this._handleParseError();
 
    var property = {
        value: value.trim(),
        priority: priority.trim()
    };
    properties.set(propertyName.trim(), property);
 
    return property;
};
 
 
module.exports = CSSStyleDeclaration;