blob: 6095951b56fc87434970033ac2064c3248265456 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This module implements the base attributes of the GuestView tags.
var $parseInt = require('safeMethods').SafeMethods.$parseInt;
var $Element = require('safeMethods').SafeMethods.$Element;
// -----------------------------------------------------------------------------
// Attribute object.
// Default implementation of a GuestView attribute.
function Attribute(name, view) {
this.dirty = false;
this.ignoreMutation = false;
this.name = name;
this.view = view;
this.defineProperty();
}
// Prevent GuestViewEvents inadvertently inheritng code from the global Object,
// allowing a pathway for unintended execution of user code.
// TODO(wjmaclean): Track down other issues of Object inheritance.
// https://crbug.com/701034
Attribute.prototype.__proto__ = null;
// Retrieves and returns the attribute's value.
Attribute.prototype.getValue = function() {
return $Element.getAttribute(this.view.element, this.name) || '';
};
// Retrieves and returns the attribute's value if it has been dirtied since
// the last time this method was called. Returns null otherwise.
Attribute.prototype.getValueIfDirty = function() {
if (!this.dirty)
return null;
this.dirty = false;
return this.getValue();
};
// Sets the attribute's value.
Attribute.prototype.setValue = function(value) {
$Element.setAttribute(this.view.element, this.name, value || '');
};
// Changes the attribute's value without triggering its mutation handler.
Attribute.prototype.setValueIgnoreMutation = function(value) {
this.ignoreMutation = true;
this.setValue(value);
this.ignoreMutation = false;
};
// Defines this attribute as a property on the view's element.
Attribute.prototype.defineProperty = function() {
$Object.defineProperty(this.view.element, this.name, {
get: $Function.bind(function() {
return this.getValue();
}, this),
set: $Function.bind(function(value) {
this.setValue(value);
}, this),
enumerable: true
});
};
// Called when the attribute's value changes.
Attribute.prototype.maybeHandleMutation = function(oldValue, newValue) {
if (this.ignoreMutation)
return;
this.dirty = true;
this.handleMutation(oldValue, newValue);
};
// Called when a change that isn't ignored occurs to the attribute's value.
Attribute.prototype.handleMutation = function(oldValue, newValue) {};
// Called when the view's element is attached to the DOM tree.
Attribute.prototype.attach = function() {};
// Called when the view's element is detached from the DOM tree.
Attribute.prototype.detach = function() {};
// -----------------------------------------------------------------------------
// BooleanAttribute object.
// An attribute that is treated as a Boolean.
function BooleanAttribute(name, view) {
$Function.call(Attribute, this, name, view);
}
BooleanAttribute.prototype.__proto__ = Attribute.prototype;
BooleanAttribute.prototype.getValue = function() {
return $Element.hasAttribute(this.view.element, this.name);
};
BooleanAttribute.prototype.setValue = function(value) {
if (!value) {
$Element.removeAttribute(this.view.element, this.name);
} else {
$Element.setAttribute(this.view.element, this.name, '');
}
};
// -----------------------------------------------------------------------------
// IntegerAttribute object.
// An attribute that is treated as an integer.
function IntegerAttribute(name, view) {
$Function.call(Attribute, this, name, view);
}
IntegerAttribute.prototype.__proto__ = Attribute.prototype;
IntegerAttribute.prototype.getValue = function() {
return $parseInt($Element.getAttribute(this.view.element, this.name)) || 0;
};
IntegerAttribute.prototype.setValue = function(value) {
$Element.setAttribute(this.view.element, this.name, $parseInt(value) || 0);
};
// -----------------------------------------------------------------------------
// ReadOnlyAttribute object.
// An attribute that cannot be changed (externally). The only way to set it
// internally is via |setValueIgnoreMutation|.
function ReadOnlyAttribute(name, view) {
$Function.call(Attribute, this, name, view);
}
ReadOnlyAttribute.prototype.__proto__ = Attribute.prototype;
ReadOnlyAttribute.prototype.handleMutation = function(oldValue, newValue) {
this.setValueIgnoreMutation(oldValue);
}
// -----------------------------------------------------------------------------
var GuestViewAttributes = {
Attribute: Attribute,
BooleanAttribute: BooleanAttribute,
IntegerAttribute: IntegerAttribute,
ReadOnlyAttribute: ReadOnlyAttribute
};
// Exports.
exports.$set('GuestViewAttributes', GuestViewAttributes);