Merge mc->Maple
This commit is contained in:
@@ -59,7 +59,7 @@ interface nsIAccessibleRelation;
|
|||||||
* Mozilla creates the implementations of nsIAccessible on demand.
|
* Mozilla creates the implementations of nsIAccessible on demand.
|
||||||
* See http://www.mozilla.org/projects/ui/accessibility for more information.
|
* See http://www.mozilla.org/projects/ui/accessibility for more information.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(3126544c-826c-4694-a2ed-67bfe56a1f37)]
|
[scriptable, uuid(e7c44e0d-736e-4ead-afee-b51f4b574020)]
|
||||||
interface nsIAccessible : nsISupports
|
interface nsIAccessible : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -110,26 +110,6 @@ interface nsIAccessible : nsISupports
|
|||||||
*/
|
*/
|
||||||
readonly attribute DOMString innerHTML;
|
readonly attribute DOMString innerHTML;
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the computed style value for this DOM node, if it is a DOM element.
|
|
||||||
* Note: the meanings of width, height and other size measurements depend
|
|
||||||
* on the version of CSS being used. Therefore, for bounds information,
|
|
||||||
* it is better to use nsIAccessible::accGetBounds.
|
|
||||||
*
|
|
||||||
* @param pseudoElt [in] The pseudo element to retrieve style for, or NULL
|
|
||||||
* for general computed style information for this node.
|
|
||||||
* @param propertyName [in] Retrieve the computed style value for this property name,
|
|
||||||
* for example "border-bottom".
|
|
||||||
*/
|
|
||||||
DOMString getComputedStyleValue(in DOMString pseudoElt, in DOMString propertyName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The method is similar to getComputedStyleValue() excepting that this one
|
|
||||||
* returns nsIDOMCSSPrimitiveValue.
|
|
||||||
*/
|
|
||||||
nsIDOMCSSPrimitiveValue getComputedStyleCSSValue(in DOMString pseudoElt,
|
|
||||||
in DOMString propertyName);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The DOM node this nsIAccessible is associated with.
|
* The DOM node this nsIAccessible is associated with.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ public:
|
|||||||
role != mozilla::a11y::roles::OPTION &&
|
role != mozilla::a11y::roles::OPTION &&
|
||||||
role != mozilla::a11y::roles::LISTITEM &&
|
role != mozilla::a11y::roles::LISTITEM &&
|
||||||
role != mozilla::a11y::roles::MENUITEM &&
|
role != mozilla::a11y::roles::MENUITEM &&
|
||||||
|
role != mozilla::a11y::roles::COMBOBOX_OPTION &&
|
||||||
|
role != mozilla::a11y::roles::PARENT_MENUITEM &&
|
||||||
role != mozilla::a11y::roles::CHECK_MENU_ITEM &&
|
role != mozilla::a11y::roles::CHECK_MENU_ITEM &&
|
||||||
role != mozilla::a11y::roles::RADIO_MENU_ITEM &&
|
role != mozilla::a11y::roles::RADIO_MENU_ITEM &&
|
||||||
role != mozilla::a11y::roles::RADIOBUTTON &&
|
role != mozilla::a11y::roles::RADIOBUTTON &&
|
||||||
@@ -83,6 +85,7 @@ private:
|
|||||||
static mozilla::a11y::role BaseRole(mozilla::a11y::role aRole)
|
static mozilla::a11y::role BaseRole(mozilla::a11y::role aRole)
|
||||||
{
|
{
|
||||||
if (aRole == mozilla::a11y::roles::CHECK_MENU_ITEM ||
|
if (aRole == mozilla::a11y::roles::CHECK_MENU_ITEM ||
|
||||||
|
aRole == mozilla::a11y::roles::PARENT_MENUITEM ||
|
||||||
aRole == mozilla::a11y::roles::RADIO_MENU_ITEM)
|
aRole == mozilla::a11y::roles::RADIO_MENU_ITEM)
|
||||||
return mozilla::a11y::roles::MENUITEM;
|
return mozilla::a11y::roles::MENUITEM;
|
||||||
return aRole;
|
return aRole;
|
||||||
|
|||||||
@@ -51,32 +51,6 @@
|
|||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::a11y;
|
using namespace mozilla::a11y;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constants and structures
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Item of the gCSSTextAttrsMap map.
|
|
||||||
*/
|
|
||||||
struct nsCSSTextAttrMapItem
|
|
||||||
{
|
|
||||||
const char* mCSSName;
|
|
||||||
const char* mCSSValue;
|
|
||||||
nsIAtom** mAttrName;
|
|
||||||
const char* mAttrValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The map of CSS properties to text attributes.
|
|
||||||
*/
|
|
||||||
const char* const kAnyValue = nsnull;
|
|
||||||
const char* const kCopyValue = nsnull;
|
|
||||||
|
|
||||||
static nsCSSTextAttrMapItem gCSSTextAttrsMap[] =
|
|
||||||
{
|
|
||||||
// CSS name CSS value Attribute name Attribute value
|
|
||||||
{ "vertical-align", kAnyValue, &nsGkAtoms::textPosition, kCopyValue }
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// TextAttrsMgr
|
// TextAttrsMgr
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -139,62 +113,61 @@ TextAttrsMgr::GetAttributes(nsIPersistentProperties* aAttributes,
|
|||||||
frame = offsetElm->GetPrimaryFrame();
|
frame = offsetElm->GetPrimaryFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTArray<TextAttr*> textAttrArray(9);
|
|
||||||
|
|
||||||
// "language" text attribute
|
// "language" text attribute
|
||||||
LangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
|
LangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
|
||||||
textAttrArray.AppendElement(&langTextAttr);
|
|
||||||
|
|
||||||
// "text-position" text attribute
|
|
||||||
CSSTextAttr posTextAttr(0, hyperTextElm, offsetElm);
|
|
||||||
textAttrArray.AppendElement(&posTextAttr);
|
|
||||||
|
|
||||||
// "background-color" text attribute
|
// "background-color" text attribute
|
||||||
BGColorTextAttr bgColorTextAttr(rootFrame, frame);
|
BGColorTextAttr bgColorTextAttr(rootFrame, frame);
|
||||||
textAttrArray.AppendElement(&bgColorTextAttr);
|
|
||||||
|
|
||||||
// "color" text attribute
|
// "color" text attribute
|
||||||
ColorTextAttr colorTextAttr(rootFrame, frame);
|
ColorTextAttr colorTextAttr(rootFrame, frame);
|
||||||
textAttrArray.AppendElement(&colorTextAttr);
|
|
||||||
|
|
||||||
// "font-family" text attribute
|
// "font-family" text attribute
|
||||||
FontFamilyTextAttr fontFamilyTextAttr(rootFrame, frame);
|
FontFamilyTextAttr fontFamilyTextAttr(rootFrame, frame);
|
||||||
textAttrArray.AppendElement(&fontFamilyTextAttr);
|
|
||||||
|
|
||||||
// "font-size" text attribute
|
// "font-size" text attribute
|
||||||
FontSizeTextAttr fontSizeTextAttr(rootFrame, frame);
|
FontSizeTextAttr fontSizeTextAttr(rootFrame, frame);
|
||||||
textAttrArray.AppendElement(&fontSizeTextAttr);
|
|
||||||
|
|
||||||
// "font-style" text attribute
|
// "font-style" text attribute
|
||||||
FontStyleTextAttr fontStyleTextAttr(rootFrame, frame);
|
FontStyleTextAttr fontStyleTextAttr(rootFrame, frame);
|
||||||
textAttrArray.AppendElement(&fontStyleTextAttr);
|
|
||||||
|
|
||||||
// "font-weight" text attribute
|
// "font-weight" text attribute
|
||||||
FontWeightTextAttr fontWeightTextAttr(rootFrame, frame);
|
FontWeightTextAttr fontWeightTextAttr(rootFrame, frame);
|
||||||
textAttrArray.AppendElement(&fontWeightTextAttr);
|
|
||||||
|
|
||||||
// "text-underline(line-through)-style(color)" text attributes
|
// "text-underline(line-through)-style(color)" text attributes
|
||||||
TextDecorTextAttr textDecorTextAttr(rootFrame, frame);
|
TextDecorTextAttr textDecorTextAttr(rootFrame, frame);
|
||||||
textAttrArray.AppendElement(&textDecorTextAttr);
|
|
||||||
|
// "text-position" text attribute
|
||||||
|
TextPosTextAttr textPosTextAttr(rootFrame, frame);
|
||||||
|
|
||||||
|
TextAttr* attrArray[] =
|
||||||
|
{
|
||||||
|
&langTextAttr,
|
||||||
|
&bgColorTextAttr,
|
||||||
|
&colorTextAttr,
|
||||||
|
&fontFamilyTextAttr,
|
||||||
|
&fontSizeTextAttr,
|
||||||
|
&fontStyleTextAttr,
|
||||||
|
&fontWeightTextAttr,
|
||||||
|
&textDecorTextAttr,
|
||||||
|
&textPosTextAttr
|
||||||
|
};
|
||||||
|
|
||||||
// Expose text attributes if applicable.
|
// Expose text attributes if applicable.
|
||||||
if (aAttributes) {
|
if (aAttributes) {
|
||||||
PRUint32 len = textAttrArray.Length();
|
for (PRUint32 idx = 0; idx < ArrayLength(attrArray); idx++)
|
||||||
for (PRUint32 idx = 0; idx < len; idx++)
|
attrArray[idx]->Expose(aAttributes, mIncludeDefAttrs);
|
||||||
textAttrArray[idx]->Expose(aAttributes, mIncludeDefAttrs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expose text attributes range where they are applied if applicable.
|
// Expose text attributes range where they are applied if applicable.
|
||||||
if (mOffsetAcc)
|
if (mOffsetAcc)
|
||||||
GetRange(textAttrArray, aStartHTOffset, aEndHTOffset);
|
GetRange(attrArray, ArrayLength(attrArray), aStartHTOffset, aEndHTOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TextAttrsMgr::GetRange(const nsTArray<TextAttr*>& aTextAttrArray,
|
TextAttrsMgr::GetRange(TextAttr* aAttrArray[], PRUint32 aAttrArrayLen,
|
||||||
PRInt32* aStartHTOffset, PRInt32* aEndHTOffset)
|
PRInt32* aStartHTOffset, PRInt32* aEndHTOffset)
|
||||||
{
|
{
|
||||||
PRUint32 attrLen = aTextAttrArray.Length();
|
|
||||||
|
|
||||||
// Navigate backward from anchor accessible to find start offset.
|
// Navigate backward from anchor accessible to find start offset.
|
||||||
for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
|
for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
|
||||||
nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
|
nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
|
||||||
@@ -209,8 +182,8 @@ TextAttrsMgr::GetRange(const nsTArray<TextAttr*>& aTextAttrArray,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
bool offsetFound = false;
|
bool offsetFound = false;
|
||||||
for (PRUint32 attrIdx = 0; attrIdx < attrLen; attrIdx++) {
|
for (PRUint32 attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
|
||||||
TextAttr* textAttr = aTextAttrArray[attrIdx];
|
TextAttr* textAttr = aAttrArray[attrIdx];
|
||||||
if (!textAttr->Equal(currElm)) {
|
if (!textAttr->Equal(currElm)) {
|
||||||
offsetFound = true;
|
offsetFound = true;
|
||||||
break;
|
break;
|
||||||
@@ -235,8 +208,8 @@ TextAttrsMgr::GetRange(const nsTArray<TextAttr*>& aTextAttrArray,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
bool offsetFound = false;
|
bool offsetFound = false;
|
||||||
for (PRUint32 attrIdx = 0; attrIdx < attrLen; attrIdx++) {
|
for (PRUint32 attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
|
||||||
TextAttr* textAttr = aTextAttrArray[attrIdx];
|
TextAttr* textAttr = aAttrArray[attrIdx];
|
||||||
|
|
||||||
// Alter the end offset when text attribute changes its value and stop
|
// Alter the end offset when text attribute changes its value and stop
|
||||||
// the search.
|
// the search.
|
||||||
@@ -293,60 +266,6 @@ TextAttrsMgr::LangTextAttr::
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CSSTextAttr
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
TextAttrsMgr::CSSTextAttr::
|
|
||||||
CSSTextAttr(PRUint32 aIndex, nsIContent* aRootElm, nsIContent* aElm) :
|
|
||||||
TTextAttr<nsString>(!aElm), mIndex(aIndex)
|
|
||||||
{
|
|
||||||
mIsRootDefined = GetValueFor(aRootElm, &mRootNativeValue);
|
|
||||||
|
|
||||||
if (aElm)
|
|
||||||
mIsDefined = GetValueFor(aElm, &mNativeValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
TextAttrsMgr::CSSTextAttr::
|
|
||||||
GetValueFor(nsIContent* aElm, nsString* aValue)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> currStyleDecl =
|
|
||||||
nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aElm);
|
|
||||||
if (!currStyleDecl)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName);
|
|
||||||
|
|
||||||
nsresult rv = currStyleDecl->GetPropertyValue(cssName, *aValue);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
const char *cssValue = gCSSTextAttrsMap[mIndex].mCSSValue;
|
|
||||||
if (cssValue != kAnyValue && !aValue->EqualsASCII(cssValue))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TextAttrsMgr::CSSTextAttr::
|
|
||||||
ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue)
|
|
||||||
{
|
|
||||||
const char* attrValue = gCSSTextAttrsMap[mIndex].mAttrValue;
|
|
||||||
if (attrValue != kCopyValue) {
|
|
||||||
nsAutoString formattedValue;
|
|
||||||
AppendASCIItoUTF16(attrValue, formattedValue);
|
|
||||||
nsAccUtils::SetAccAttr(aAttributes, *gCSSTextAttrsMap[mIndex].mAttrName,
|
|
||||||
formattedValue);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAccUtils::SetAccAttr(aAttributes, *gCSSTextAttrsMap[mIndex].mAttrName,
|
|
||||||
aValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// BGColorTextAttr
|
// BGColorTextAttr
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -742,3 +661,104 @@ TextAttrsMgr::TextDecorTextAttr::
|
|||||||
formattedColor);
|
formattedColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// TextPosTextAttr
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TextAttrsMgr::TextPosTextAttr::
|
||||||
|
TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
|
||||||
|
TTextAttr<TextPosValue>(!aFrame)
|
||||||
|
{
|
||||||
|
mRootNativeValue = GetTextPosValue(aRootFrame);
|
||||||
|
mIsRootDefined = mRootNativeValue != eTextPosNone;
|
||||||
|
|
||||||
|
if (aFrame) {
|
||||||
|
mNativeValue = GetTextPosValue(aFrame);
|
||||||
|
mIsDefined = mNativeValue != eTextPosNone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TextAttrsMgr::TextPosTextAttr::
|
||||||
|
GetValueFor(nsIContent* aContent, TextPosValue* aValue)
|
||||||
|
{
|
||||||
|
nsIFrame* frame = aContent->GetPrimaryFrame();
|
||||||
|
if (frame) {
|
||||||
|
*aValue = GetTextPosValue(frame);
|
||||||
|
return *aValue != eTextPosNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextAttrsMgr::TextPosTextAttr::
|
||||||
|
ExposeValue(nsIPersistentProperties* aAttributes, const TextPosValue& aValue)
|
||||||
|
{
|
||||||
|
switch (aValue) {
|
||||||
|
case eTextPosBaseline:
|
||||||
|
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
|
||||||
|
NS_LITERAL_STRING("baseline"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eTextPosSub:
|
||||||
|
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
|
||||||
|
NS_LITERAL_STRING("sub"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eTextPosSuper:
|
||||||
|
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
|
||||||
|
NS_LITERAL_STRING("super"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextAttrsMgr::TextPosValue
|
||||||
|
TextAttrsMgr::TextPosTextAttr::
|
||||||
|
GetTextPosValue(nsIFrame* aFrame) const
|
||||||
|
{
|
||||||
|
const nsStyleCoord& styleCoord = aFrame->GetStyleTextReset()->mVerticalAlign;
|
||||||
|
switch (styleCoord.GetUnit()) {
|
||||||
|
case eStyleUnit_Enumerated:
|
||||||
|
switch (styleCoord.GetIntValue()) {
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_BASELINE:
|
||||||
|
return eTextPosBaseline;
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_SUB:
|
||||||
|
return eTextPosSub;
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_SUPER:
|
||||||
|
return eTextPosSuper;
|
||||||
|
|
||||||
|
// No good guess for these:
|
||||||
|
// NS_STYLE_VERTICAL_ALIGN_TOP
|
||||||
|
// NS_STYLE_VERTICAL_ALIGN_TEXT_TOP
|
||||||
|
// NS_STYLE_VERTICAL_ALIGN_MIDDLE
|
||||||
|
// NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM
|
||||||
|
// NS_STYLE_VERTICAL_ALIGN_BOTTOM
|
||||||
|
// NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE
|
||||||
|
// Do not expose value of text-position attribute.
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return eTextPosNone;
|
||||||
|
|
||||||
|
case eStyleUnit_Percent:
|
||||||
|
{
|
||||||
|
float percentValue = styleCoord.GetPercentValue();
|
||||||
|
return percentValue > 0 ?
|
||||||
|
eTextPosSuper :
|
||||||
|
(percentValue < 0 ? eTextPosSub : eTextPosBaseline);
|
||||||
|
}
|
||||||
|
|
||||||
|
case eStyleUnit_Coord:
|
||||||
|
{
|
||||||
|
nscoord coordValue = styleCoord.GetCoordValue();
|
||||||
|
return coordValue > 0 ?
|
||||||
|
eTextPosSuper :
|
||||||
|
(coordValue < 0 ? eTextPosSub : eTextPosBaseline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eTextPosNone;
|
||||||
|
}
|
||||||
|
|||||||
@@ -107,11 +107,12 @@ protected:
|
|||||||
* its value before or after the given offsets.
|
* its value before or after the given offsets.
|
||||||
*
|
*
|
||||||
* @param aTextAttrArray [in] text attributes array
|
* @param aTextAttrArray [in] text attributes array
|
||||||
|
* @param aAttrArrayLen [in] text attributes array length
|
||||||
* @param aStartHTOffset [in, out] the start offset
|
* @param aStartHTOffset [in, out] the start offset
|
||||||
* @param aEndHTOffset [in, out] the end offset
|
* @param aEndHTOffset [in, out] the end offset
|
||||||
*/
|
*/
|
||||||
class TextAttr;
|
class TextAttr;
|
||||||
void GetRange(const nsTArray<TextAttr*>& aTextAttrArray,
|
void GetRange(TextAttr* aAttrArray[], PRUint32 aAttrArrayLen,
|
||||||
PRInt32* aStartHTOffset, PRInt32* aEndHTOffset);
|
PRInt32* aStartHTOffset, PRInt32* aEndHTOffset);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -157,7 +158,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
TTextAttr(bool aGetRootValue) : mGetRootValue(aGetRootValue) {}
|
TTextAttr(bool aGetRootValue) : mGetRootValue(aGetRootValue) {}
|
||||||
|
|
||||||
// ITextAttr
|
// TextAttr
|
||||||
virtual void Expose(nsIPersistentProperties* aAttributes,
|
virtual void Expose(nsIPersistentProperties* aAttributes,
|
||||||
bool aIncludeDefAttrValue)
|
bool aIncludeDefAttrValue)
|
||||||
{
|
{
|
||||||
@@ -242,27 +243,6 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class is used for the work with CSS based text attributes.
|
|
||||||
*/
|
|
||||||
class CSSTextAttr : public TTextAttr<nsString>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CSSTextAttr(PRUint32 aIndex, nsIContent* aRootElm, nsIContent* aElm);
|
|
||||||
virtual ~CSSTextAttr() { }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// TextAttr
|
|
||||||
virtual bool GetValueFor(nsIContent* aElm, nsString* aValue);
|
|
||||||
virtual void ExposeValue(nsIPersistentProperties* aAttributes,
|
|
||||||
const nsString& aValue);
|
|
||||||
|
|
||||||
private:
|
|
||||||
PRInt32 mIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class is used for the work with 'background-color' text attribute.
|
* Class is used for the work with 'background-color' text attribute.
|
||||||
*/
|
*/
|
||||||
@@ -435,6 +415,34 @@ protected:
|
|||||||
const TextDecorValue& aValue);
|
const TextDecorValue& aValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class is used for the work with "text-position" text attribute.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum TextPosValue {
|
||||||
|
eTextPosNone = 0,
|
||||||
|
eTextPosBaseline,
|
||||||
|
eTextPosSub,
|
||||||
|
eTextPosSuper
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextPosTextAttr : public TTextAttr<TextPosValue>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
|
||||||
|
virtual ~TextPosTextAttr() { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// TextAttr
|
||||||
|
virtual bool GetValueFor(nsIContent* aElm, TextPosValue* aValue);
|
||||||
|
virtual void ExposeValue(nsIPersistentProperties* aAttributes,
|
||||||
|
const TextPosValue& aValue);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextPosValue GetTextPosValue(nsIFrame* aFrame) const;
|
||||||
|
};
|
||||||
|
|
||||||
}; // TextAttrMgr
|
}; // TextAttrMgr
|
||||||
|
|
||||||
} // namespace a11y
|
} // namespace a11y
|
||||||
|
|||||||
@@ -175,70 +175,6 @@ nsAccUtils::GetPositionAndSizeForXULSelectControlItem(nsIContent *aContent,
|
|||||||
(*aPosInSet)++; // group position is 1-index based.
|
(*aPosInSet)++; // group position is 1-index based.
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIContent *aContent,
|
|
||||||
PRInt32 *aPosInSet,
|
|
||||||
PRInt32 *aSetSize)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMXULContainerItemElement> item(do_QueryInterface(aContent));
|
|
||||||
if (!item)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMXULContainerElement> container;
|
|
||||||
item->GetParentContainer(getter_AddRefs(container));
|
|
||||||
if (!container)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Get item count.
|
|
||||||
PRUint32 itemsCount = 0;
|
|
||||||
container->GetItemCount(&itemsCount);
|
|
||||||
|
|
||||||
// Get item index.
|
|
||||||
PRInt32 indexOf = 0;
|
|
||||||
container->GetIndexOfItem(item, &indexOf);
|
|
||||||
|
|
||||||
// Calculate set size and position in the set.
|
|
||||||
*aSetSize = 0, *aPosInSet = 0;
|
|
||||||
for (PRInt32 index = indexOf; index >= 0; index--) {
|
|
||||||
nsCOMPtr<nsIDOMXULElement> item;
|
|
||||||
container->GetItemAtIndex(index, getter_AddRefs(item));
|
|
||||||
nsCOMPtr<nsINode> itemNode(do_QueryInterface(item));
|
|
||||||
|
|
||||||
nsAccessible* itemAcc = itemNode ?
|
|
||||||
GetAccService()->GetAccessible(itemNode, nsnull) : nsnull;
|
|
||||||
|
|
||||||
if (itemAcc) {
|
|
||||||
PRUint32 itemRole = Role(itemAcc);
|
|
||||||
if (itemRole == nsIAccessibleRole::ROLE_SEPARATOR)
|
|
||||||
break; // We reached the beginning of our group.
|
|
||||||
|
|
||||||
if (!(itemAcc->State() & states::INVISIBLE)) {
|
|
||||||
(*aSetSize)++;
|
|
||||||
(*aPosInSet)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (PRInt32 index = indexOf + 1; index < static_cast<PRInt32>(itemsCount);
|
|
||||||
index++) {
|
|
||||||
nsCOMPtr<nsIDOMXULElement> item;
|
|
||||||
container->GetItemAtIndex(index, getter_AddRefs(item));
|
|
||||||
nsCOMPtr<nsINode> itemNode(do_QueryInterface(item));
|
|
||||||
|
|
||||||
nsAccessible* itemAcc =
|
|
||||||
itemNode ? GetAccService()->GetAccessible(itemNode, nsnull) : nsnull;
|
|
||||||
|
|
||||||
if (itemAcc) {
|
|
||||||
PRUint32 itemRole = Role(itemAcc);
|
|
||||||
if (itemRole == nsIAccessibleRole::ROLE_SEPARATOR)
|
|
||||||
break; // We reached the end of our group.
|
|
||||||
|
|
||||||
if (!(itemAcc->State() & states::INVISIBLE))
|
|
||||||
(*aSetSize)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PRInt32
|
PRInt32
|
||||||
nsAccUtils::GetLevelForXULContainerItem(nsIContent *aContent)
|
nsAccUtils::GetLevelForXULContainerItem(nsIContent *aContent)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -115,14 +115,6 @@ public:
|
|||||||
PRInt32 *aPosInSet,
|
PRInt32 *aPosInSet,
|
||||||
PRInt32 *aSetSize);
|
PRInt32 *aSetSize);
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute group position and group size (posinset and setsize) for
|
|
||||||
* nsIDOMXULContainerItemElement node.
|
|
||||||
*/
|
|
||||||
static void GetPositionAndSizeForXULContainerItem(nsIContent *aContent,
|
|
||||||
PRInt32 *aPosInSet,
|
|
||||||
PRInt32 *aSetSize);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute group level for nsIDOMXULContainerItemElement node.
|
* Compute group level for nsIDOMXULContainerItemElement node.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -231,42 +231,6 @@ nsAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
|
|||||||
mRoleMapEntry = aRoleMapEntry;
|
mRoleMapEntry = aRoleMapEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsAccessible::GetComputedStyleValue(const nsAString& aPseudoElt,
|
|
||||||
const nsAString& aPropertyName,
|
|
||||||
nsAString& aValue)
|
|
||||||
{
|
|
||||||
if (IsDefunct())
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
|
|
||||||
nsCoreUtils::GetComputedStyleDeclaration(aPseudoElt, mContent);
|
|
||||||
NS_ENSURE_TRUE(styleDecl, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
return styleDecl->GetPropertyValue(aPropertyName, aValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsAccessible::GetComputedStyleCSSValue(const nsAString& aPseudoElt,
|
|
||||||
const nsAString& aPropertyName,
|
|
||||||
nsIDOMCSSPrimitiveValue **aCSSValue) {
|
|
||||||
NS_ENSURE_ARG_POINTER(aCSSValue);
|
|
||||||
*aCSSValue = nsnull;
|
|
||||||
|
|
||||||
if (IsDefunct())
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
|
|
||||||
nsCoreUtils::GetComputedStyleDeclaration(aPseudoElt, mContent);
|
|
||||||
NS_ENSURE_STATE(styleDecl);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMCSSValue> cssValue;
|
|
||||||
styleDecl->GetPropertyCSSValue(aPropertyName, getter_AddRefs(cssValue));
|
|
||||||
NS_ENSURE_TRUE(cssValue, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
return CallQueryInterface(cssValue, aCSSValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsAccessible::GetDocument(nsIAccessibleDocument **aDocument)
|
nsAccessible::GetDocument(nsIAccessibleDocument **aDocument)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -467,24 +467,6 @@ nsApplicationAccessible::ScrollToPoint(PRUint32 aCoordinateType,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsApplicationAccessible::GetComputedStyleValue(const nsAString &aPseudoElt,
|
|
||||||
const nsAString &aPropertyName,
|
|
||||||
nsAString &aValue)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsApplicationAccessible::GetComputedStyleCSSValue(const nsAString &aPseudoElt,
|
|
||||||
const nsAString &aPropertyName,
|
|
||||||
nsIDOMCSSPrimitiveValue **aCSSPrimitiveValue)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aCSSPrimitiveValue);
|
|
||||||
*aCSSPrimitiveValue = nsnull;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsApplicationAccessible::GetLanguage(nsAString &aLanguage)
|
nsApplicationAccessible::GetLanguage(nsAString &aLanguage)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -76,12 +76,6 @@ public:
|
|||||||
NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
|
NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
|
||||||
NS_SCRIPTABLE NS_IMETHOD ScrollTo(PRUint32 aScrollType);
|
NS_SCRIPTABLE NS_IMETHOD ScrollTo(PRUint32 aScrollType);
|
||||||
NS_SCRIPTABLE NS_IMETHOD ScrollToPoint(PRUint32 aCoordinateType, PRInt32 aX, PRInt32 aY);
|
NS_SCRIPTABLE NS_IMETHOD ScrollToPoint(PRUint32 aCoordinateType, PRInt32 aX, PRInt32 aY);
|
||||||
NS_SCRIPTABLE NS_IMETHOD GetComputedStyleValue(const nsAString& aPseudoElt,
|
|
||||||
const nsAString& aPropertyName,
|
|
||||||
nsAString& aValue NS_OUTPARAM);
|
|
||||||
NS_SCRIPTABLE NS_IMETHOD GetComputedStyleCSSValue(const nsAString& aPseudoElt,
|
|
||||||
const nsAString& aPropertyName,
|
|
||||||
nsIDOMCSSPrimitiveValue** aValue NS_OUTPARAM);
|
|
||||||
NS_SCRIPTABLE NS_IMETHOD GetLanguage(nsAString& aLanguage);
|
NS_SCRIPTABLE NS_IMETHOD GetLanguage(nsAString& aLanguage);
|
||||||
NS_IMETHOD GetParent(nsIAccessible **aParent);
|
NS_IMETHOD GetParent(nsIAccessible **aParent);
|
||||||
NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
|
NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
|
||||||
|
|||||||
@@ -570,26 +570,6 @@ nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
|
|||||||
walkUp = walkUp->GetParent();
|
walkUp = walkUp->GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIDOMCSSStyleDeclaration>
|
|
||||||
nsCoreUtils::GetComputedStyleDeclaration(const nsAString& aPseudoElt,
|
|
||||||
nsIContent *aContent)
|
|
||||||
{
|
|
||||||
nsIContent* content = GetDOMElementFor(aContent);
|
|
||||||
if (!content)
|
|
||||||
return nsnull;
|
|
||||||
|
|
||||||
// Returns number of items in style declaration
|
|
||||||
nsCOMPtr<nsIDOMWindow> window =
|
|
||||||
do_QueryInterface(content->OwnerDoc()->GetWindow());
|
|
||||||
if (!window)
|
|
||||||
return nsnull;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
|
||||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(content));
|
|
||||||
window->GetComputedStyle(domElement, aPseudoElt, getter_AddRefs(cssDecl));
|
|
||||||
return cssDecl.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<nsIBoxObject>
|
already_AddRefed<nsIBoxObject>
|
||||||
nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
|
nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -288,13 +288,6 @@ public:
|
|||||||
static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
|
static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
|
||||||
nsAString& aLanguage);
|
nsAString& aLanguage);
|
||||||
|
|
||||||
/**
|
|
||||||
* Return computed styles declaration for the given node.
|
|
||||||
*/
|
|
||||||
static already_AddRefed<nsIDOMCSSStyleDeclaration>
|
|
||||||
GetComputedStyleDeclaration(const nsAString& aPseudoElt,
|
|
||||||
nsIContent *aContent);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return box object for XUL treechildren element by tree box object.
|
* Return box object for XUL treechildren element by tree box object.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1441,9 +1441,26 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
|
|||||||
if (rowElm->IsHTML() && rowElm->Tag() == nsGkAtoms::tr) {
|
if (rowElm->IsHTML() && rowElm->Tag() == nsGkAtoms::tr) {
|
||||||
for (nsIContent* cellElm = rowElm->GetFirstChild(); cellElm;
|
for (nsIContent* cellElm = rowElm->GetFirstChild(); cellElm;
|
||||||
cellElm = cellElm->GetNextSibling()) {
|
cellElm = cellElm->GetNextSibling()) {
|
||||||
if (cellElm->IsHTML() && cellElm->Tag() == nsGkAtoms::th) {
|
if (cellElm->IsHTML()) {
|
||||||
RETURN_LAYOUT_ANSWER(false,
|
|
||||||
"Has th -- legitimate table structures");
|
if (cellElm->NodeInfo()->Equals(nsGkAtoms::th)) {
|
||||||
|
RETURN_LAYOUT_ANSWER(false,
|
||||||
|
"Has th -- legitimate table structures");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::headers) ||
|
||||||
|
cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::scope) ||
|
||||||
|
cellElm->HasAttr(kNameSpaceID_None, nsGkAtoms::abbr)) {
|
||||||
|
RETURN_LAYOUT_ANSWER(false,
|
||||||
|
"Has headers, scope, or abbr attribute -- legitimate table structures");
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAccessible* cell = mDoc->GetAccessible(cellElm);
|
||||||
|
if (cell && cell->GetChildCount() == 1 &&
|
||||||
|
cell->FirstChild()->IsAbbreviation()) {
|
||||||
|
RETURN_LAYOUT_ANSWER(false,
|
||||||
|
"has abbr -- legitimate table structures");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,8 @@
|
|||||||
#include "AccessibleComponent_i.c"
|
#include "AccessibleComponent_i.c"
|
||||||
|
|
||||||
#include "nsAccessible.h"
|
#include "nsAccessible.h"
|
||||||
|
#include "nsCoreUtils.h"
|
||||||
|
#include "nsWinUtils.h"
|
||||||
#include "States.h"
|
#include "States.h"
|
||||||
|
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
@@ -156,17 +158,23 @@ __try {
|
|||||||
*aColorValue = 0;
|
*aColorValue = 0;
|
||||||
|
|
||||||
nsRefPtr<nsAccessible> acc(do_QueryObject(this));
|
nsRefPtr<nsAccessible> acc(do_QueryObject(this));
|
||||||
if (!acc)
|
if (acc->IsDefunct())
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> cssValue;
|
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
|
||||||
nsresult rv = acc->GetComputedStyleCSSValue(EmptyString(), aPropName,
|
nsWinUtils::GetComputedStyleDeclaration(acc->GetContent());
|
||||||
getter_AddRefs(cssValue));
|
NS_ENSURE_STATE(styleDecl);
|
||||||
if (NS_FAILED(rv) || !cssValue)
|
|
||||||
return GetHRESULT(rv);
|
nsCOMPtr<nsIDOMCSSValue> cssGenericValue;
|
||||||
|
styleDecl->GetPropertyCSSValue(aPropName, getter_AddRefs(cssGenericValue));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMCSSPrimitiveValue> cssValue =
|
||||||
|
do_QueryInterface(cssGenericValue);
|
||||||
|
if (!cssValue)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMRGBColor> rgbColor;
|
nsCOMPtr<nsIDOMRGBColor> rgbColor;
|
||||||
rv = cssValue->GetRGBColorValue(getter_AddRefs(rgbColor));
|
nsresult rv = cssValue->GetRGBColorValue(getter_AddRefs(rgbColor));
|
||||||
if (NS_FAILED(rv) || !rgbColor)
|
if (NS_FAILED(rv) || !rgbColor)
|
||||||
return GetHRESULT(rv);
|
return GetHRESULT(rv);
|
||||||
|
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ __try{
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
|
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
|
||||||
nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), mContent);
|
nsWinUtils::GetComputedStyleDeclaration(mContent);
|
||||||
NS_ENSURE_TRUE(cssDecl, E_FAIL);
|
NS_ENSURE_TRUE(cssDecl, E_FAIL);
|
||||||
|
|
||||||
PRUint32 length;
|
PRUint32 length;
|
||||||
@@ -374,7 +374,7 @@ __try {
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
|
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
|
||||||
nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), mContent);
|
nsWinUtils::GetComputedStyleDeclaration(mContent);
|
||||||
NS_ENSURE_TRUE(cssDecl, E_FAIL);
|
NS_ENSURE_TRUE(cssDecl, E_FAIL);
|
||||||
|
|
||||||
PRUint32 index;
|
PRUint32 index;
|
||||||
|
|||||||
@@ -55,6 +55,25 @@ using namespace mozilla::a11y;
|
|||||||
// tab windows.
|
// tab windows.
|
||||||
const PRUnichar* kPropNameTabContent = L"AccessibleTabWindow";
|
const PRUnichar* kPropNameTabContent = L"AccessibleTabWindow";
|
||||||
|
|
||||||
|
already_AddRefed<nsIDOMCSSStyleDeclaration>
|
||||||
|
nsWinUtils::GetComputedStyleDeclaration(nsIContent* aContent)
|
||||||
|
{
|
||||||
|
nsIContent* elm = nsCoreUtils::GetDOMElementFor(aContent);
|
||||||
|
if (!elm)
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
|
// Returns number of items in style declaration
|
||||||
|
nsCOMPtr<nsIDOMWindow> window =
|
||||||
|
do_QueryInterface(elm->OwnerDoc()->GetWindow());
|
||||||
|
if (!window)
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
||||||
|
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(elm));
|
||||||
|
window->GetComputedStyle(domElement, EmptyString(), getter_AddRefs(cssDecl));
|
||||||
|
return cssDecl.forget();
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
|
nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
|
||||||
long *aIA2ArrayLen)
|
long *aIA2ArrayLen)
|
||||||
|
|||||||
@@ -52,6 +52,15 @@ const LPCWSTR kClassNameTabContent = L"MozillaContentWindowClass";
|
|||||||
class nsWinUtils
|
class nsWinUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Return computed styles declaration for the given node.
|
||||||
|
*
|
||||||
|
* @note Please use it carefully since it can shutdown the accessible tree
|
||||||
|
* you operate on.
|
||||||
|
*/
|
||||||
|
static already_AddRefed<nsIDOMCSSStyleDeclaration>
|
||||||
|
GetComputedStyleDeclaration(nsIContent* aContent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert nsIArray array of accessible objects to an array of IUnknown*
|
* Convert nsIArray array of accessible objects to an array of IUnknown*
|
||||||
* objects used in IA2 methods.
|
* objects used in IA2 methods.
|
||||||
|
|||||||
@@ -311,14 +311,6 @@ nsXULMenuitemAccessible::GetLevelInternal()
|
|||||||
return nsAccUtils::GetLevelForXULContainerItem(mContent);
|
return nsAccUtils::GetLevelForXULContainerItem(mContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsXULMenuitemAccessible::GetPositionAndSizeInternal(PRInt32 *aPosInSet,
|
|
||||||
PRInt32 *aSetSize)
|
|
||||||
{
|
|
||||||
nsAccUtils::GetPositionAndSizeForXULContainerItem(mContent, aPosInSet,
|
|
||||||
aSetSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsXULMenuitemAccessible::CanHaveAnonChildren()
|
nsXULMenuitemAccessible::CanHaveAnonChildren()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ public:
|
|||||||
virtual mozilla::a11y::role NativeRole();
|
virtual mozilla::a11y::role NativeRole();
|
||||||
virtual PRUint64 NativeState();
|
virtual PRUint64 NativeState();
|
||||||
virtual PRInt32 GetLevelInternal();
|
virtual PRInt32 GetLevelInternal();
|
||||||
virtual void GetPositionAndSizeInternal(PRInt32 *aPosInSet,
|
|
||||||
PRInt32 *aSetSize);
|
|
||||||
|
|
||||||
virtual bool CanHaveAnonChildren();
|
virtual bool CanHaveAnonChildren();
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ _TEST_FILES =\
|
|||||||
test_descr.html \
|
test_descr.html \
|
||||||
test_nsIAccessibleDocument.html \
|
test_nsIAccessibleDocument.html \
|
||||||
test_nsIAccessibleImage.html \
|
test_nsIAccessibleImage.html \
|
||||||
test_nsIAccessNode_utils.html \
|
|
||||||
test_nsOuterDocAccessible.html \
|
test_nsOuterDocAccessible.html \
|
||||||
test_role_nsHyperTextAcc.html \
|
test_role_nsHyperTextAcc.html \
|
||||||
test_textboxes.html \
|
test_textboxes.html \
|
||||||
|
|||||||
@@ -139,6 +139,13 @@
|
|||||||
testGroupAttrs("h5", 0, 0, 5);
|
testGroupAttrs("h5", 0, 0, 5);
|
||||||
testGroupAttrs("h6", 0, 0, 6);
|
testGroupAttrs("h6", 0, 0, 6);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// ARIA combobox
|
||||||
|
testGroupAttrs("combo1_opt1", 1, 4);
|
||||||
|
testGroupAttrs("combo1_opt2", 2, 4);
|
||||||
|
testGroupAttrs("combo1_opt3", 3, 4);
|
||||||
|
testGroupAttrs("combo1_opt4", 4, 4);
|
||||||
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,5 +312,12 @@
|
|||||||
<h5 id="h5">heading5</h5>
|
<h5 id="h5">heading5</h5>
|
||||||
<h6 id="h6">heading6</h6>
|
<h6 id="h6">heading6</h6>
|
||||||
|
|
||||||
|
<ul id="combo1" role="combobox">Password
|
||||||
|
<li id="combo1_opt1" role="option">Xyzzy</li>
|
||||||
|
<li id="combo1_opt2" role="option">Plughs</li>
|
||||||
|
<li id="combo1_opt3" role="option">Shazaam</li>
|
||||||
|
<li id="combo1_opt4" role="option">JoeSentMe</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -90,6 +90,13 @@
|
|||||||
testGroupAttrs("radio1", 1, 2);
|
testGroupAttrs("radio1", 1, 2);
|
||||||
testGroupAttrs("radio2", 2, 2);
|
testGroupAttrs("radio2", 2, 2);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// xul:menulist
|
||||||
|
testGroupAttrs("menulist1.1", 1);
|
||||||
|
testGroupAttrs("menulist1.2", 2);
|
||||||
|
testGroupAttrs("menulist1.3", 3);
|
||||||
|
testGroupAttrs("menulist1.4", 4);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// ARIA menu (bug 441888)
|
// ARIA menu (bug 441888)
|
||||||
testGroupAttrs("aria-menuitem", 1, 3);
|
testGroupAttrs("aria-menuitem", 1, 3);
|
||||||
@@ -175,6 +182,15 @@
|
|||||||
<radio id="radio2" label="radio2"/>
|
<radio id="radio2" label="radio2"/>
|
||||||
</radiogroup>
|
</radiogroup>
|
||||||
|
|
||||||
|
<menulist id="menulist1" label="Vehicle">
|
||||||
|
<menupopup>
|
||||||
|
<menuitem id="menulist1.1" label="Car"/>
|
||||||
|
<menuitem id="menulist1.2" label="Taxi"/>
|
||||||
|
<menuitem id="menulist1.3" label="Bus" selected="true"/>
|
||||||
|
<menuitem id="menulist1.4" label="Train"/>
|
||||||
|
</menupopup>
|
||||||
|
</menulist>
|
||||||
|
|
||||||
<vbox>
|
<vbox>
|
||||||
<description role="menuitem" id="aria-menuitem"
|
<description role="menuitem" id="aria-menuitem"
|
||||||
value="conventional menuitem"/>
|
value="conventional menuitem"/>
|
||||||
|
|||||||
@@ -181,6 +181,30 @@
|
|||||||
attrs = {"text-position": gComputedStyle.verticalAlign};
|
attrs = {"text-position": gComputedStyle.verticalAlign};
|
||||||
testTextAttrs(ID, 55, attrs, defAttrs, 55, 64);
|
testTextAttrs(ID, 55, attrs, defAttrs, 55, 64);
|
||||||
|
|
||||||
|
attrs = {};
|
||||||
|
testTextAttrs(ID, 64, attrs, defAttrs, 64, 69);
|
||||||
|
|
||||||
|
attrs = { "text-position": "super" };
|
||||||
|
testTextAttrs(ID, 69, attrs, defAttrs, 69, 84);
|
||||||
|
|
||||||
|
attrs = {};
|
||||||
|
testTextAttrs(ID, 84, attrs, defAttrs, 84, 89);
|
||||||
|
|
||||||
|
attrs = { "text-position": "sub" };
|
||||||
|
testTextAttrs(ID, 89, attrs, defAttrs, 89, 102);
|
||||||
|
|
||||||
|
attrs = {};
|
||||||
|
testTextAttrs(ID, 102, attrs, defAttrs, 102, 107);
|
||||||
|
|
||||||
|
attrs = { "text-position": "super" };
|
||||||
|
testTextAttrs(ID, 107, attrs, defAttrs, 107, 123);
|
||||||
|
|
||||||
|
attrs = {};
|
||||||
|
testTextAttrs(ID, 123, attrs, defAttrs, 123, 128);
|
||||||
|
|
||||||
|
attrs = { "text-position": "sub" };
|
||||||
|
testTextAttrs(ID, 128, attrs, defAttrs, 128, 142);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// area7
|
// area7
|
||||||
ID = "area7";
|
ID = "area7";
|
||||||
@@ -505,6 +529,11 @@
|
|||||||
title="Implement text attributes">
|
title="Implement text attributes">
|
||||||
Mozilla Bug 345759
|
Mozilla Bug 345759
|
||||||
</a>
|
</a>
|
||||||
|
<a target="_blank"
|
||||||
|
href="https://bugzilla.mozilla.org/show_bug.cgi?id=473569"
|
||||||
|
title="Restrict text-position to allowed values">
|
||||||
|
Mozilla Bug 473569
|
||||||
|
</a>
|
||||||
<a target="_blank"
|
<a target="_blank"
|
||||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=473576"
|
href="https://bugzilla.mozilla.org/show_bug.cgi?id=473576"
|
||||||
title="font-family text attribute should expose actual font used">
|
title="font-family text attribute should expose actual font used">
|
||||||
@@ -549,7 +578,11 @@
|
|||||||
This <sup>sentence</sup> has the word
|
This <sup>sentence</sup> has the word
|
||||||
<span style="vertical-align:super;">sentence</span> in
|
<span style="vertical-align:super;">sentence</span> in
|
||||||
<sub>superscript</sub> and
|
<sub>superscript</sub> and
|
||||||
<span style="vertical-align:sub;">subscript</span>
|
<span style="vertical-align:sub;">subscript</span> and
|
||||||
|
<span style="vertical-align:20%;">superscript 20%</span> and
|
||||||
|
<span style="vertical-align:-20%;">subscript 20%</span> and
|
||||||
|
<span style="vertical-align:20px;">superscript 20px</span> and
|
||||||
|
<span style="vertical-align:-20px;">subscript 20px</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p lang="en" id="area7">
|
<p lang="en" id="area7">
|
||||||
|
|||||||
@@ -35,21 +35,39 @@
|
|||||||
// table with caption
|
// table with caption
|
||||||
testAbsentAttrs("table4", attr);
|
testAbsentAttrs("table4", attr);
|
||||||
|
|
||||||
// table with empty caption
|
// layout table with empty caption
|
||||||
testAttrs("table4.2", attr, true);
|
testAttrs("table4.2", attr, true);
|
||||||
|
|
||||||
// table with th element
|
// table with thead element
|
||||||
testAbsentAttrs("table5", attr);
|
testAbsentAttrs("table5", attr);
|
||||||
|
|
||||||
// table with thead element
|
|
||||||
testAbsentAttrs("table6", attr);
|
|
||||||
|
|
||||||
// table with tfoot element
|
// table with tfoot element
|
||||||
testAbsentAttrs("table7", attr);
|
testAbsentAttrs("table5.1", attr);
|
||||||
|
|
||||||
// table with colgroup or col elements
|
// table with colgroup or col elements
|
||||||
testAbsentAttrs("table8", attr);
|
testAbsentAttrs("table5.2", attr);
|
||||||
testAbsentAttrs("table8.2", attr);
|
testAbsentAttrs("table5.3", attr);
|
||||||
|
|
||||||
|
// table with th element
|
||||||
|
testAbsentAttrs("table6", attr);
|
||||||
|
|
||||||
|
// table with headers attribute
|
||||||
|
testAbsentAttrs("table6.2", attr);
|
||||||
|
|
||||||
|
// table with scope attribute
|
||||||
|
testAbsentAttrs("table6.2.2", attr);
|
||||||
|
|
||||||
|
// table with abbr attribute
|
||||||
|
testAbsentAttrs("table6.2.3", attr);
|
||||||
|
|
||||||
|
// table with abbr element
|
||||||
|
testAbsentAttrs("table6.3", attr);
|
||||||
|
|
||||||
|
// table with abbr element having empty text node
|
||||||
|
testAbsentAttrs("table6.4", attr);
|
||||||
|
|
||||||
|
// table with abbr element and non-empty text node
|
||||||
|
testAttrs("table6.5", attr, true);
|
||||||
|
|
||||||
// layout table with nested table
|
// layout table with nested table
|
||||||
testAttrs("table9", attr, true);
|
testAttrs("table9", attr, true);
|
||||||
@@ -125,6 +143,11 @@
|
|||||||
title="Expose layout-guess: true object attribute on CSS table accessible">
|
title="Expose layout-guess: true object attribute on CSS table accessible">
|
||||||
Mozilla Bug 693948
|
Mozilla Bug 693948
|
||||||
</a>
|
</a>
|
||||||
|
<a target="_blank"
|
||||||
|
href="https://bugzilla.mozilla.org/show_bug.cgi?id=696975"
|
||||||
|
title="Extend the list of legitimate data table structures">
|
||||||
|
Mozilla Bug 696975
|
||||||
|
</a>
|
||||||
|
|
||||||
<p id="display"></p>
|
<p id="display"></p>
|
||||||
<div id="content" style="display: none"></div>
|
<div id="content" style="display: none"></div>
|
||||||
@@ -200,7 +223,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- table with empty caption -->
|
<!-- layout table with empty caption -->
|
||||||
<table id="table4.2">
|
<table id="table4.2">
|
||||||
<caption> </caption>
|
<caption> </caption>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -208,15 +231,8 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- table with th element -->
|
|
||||||
<table id="table5">
|
|
||||||
<tr>
|
|
||||||
<th>Cell1</th><th>cell2</th>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- table with thead element -->
|
<!-- table with thead element -->
|
||||||
<table id="table6">
|
<table id="table5">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Cell1</td><td>cell2</td>
|
<td>Cell1</td><td>cell2</td>
|
||||||
@@ -225,7 +241,7 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- table with tfoot element -->
|
<!-- table with tfoot element -->
|
||||||
<table id="table7">
|
<table id="table5.1">
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Cell1</td><td>cell2</td>
|
<td>Cell1</td><td>cell2</td>
|
||||||
@@ -234,19 +250,73 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- table with colgroup and col elements -->
|
<!-- table with colgroup and col elements -->
|
||||||
<table id="table8">
|
<table id="table5.2">
|
||||||
<colgroup width="20"></colgroup>
|
<colgroup width="20"></colgroup>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Cell1</td><td>cell2</td>
|
<td>Cell1</td><td>cell2</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<table id="table8.2">
|
<table id="table5.3">
|
||||||
<col width="20">
|
<col width="20">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Cell1</td><td>cell2</td>
|
<td>Cell1</td><td>cell2</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<!-- table with th element -->
|
||||||
|
<table id="table6">
|
||||||
|
<tr>
|
||||||
|
<th>Cell1</th><th>cell2</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- table with headers attribute -->
|
||||||
|
<table id="table6.2">
|
||||||
|
<tr>
|
||||||
|
<td headers="a">table6.2 cell</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- table with scope attribute -->
|
||||||
|
<table id="table6.2.2">
|
||||||
|
<tr>
|
||||||
|
<td scope="a">table6.2.2 cell</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- table with abbr attribute -->
|
||||||
|
<table id="table6.2.3">
|
||||||
|
<tr>
|
||||||
|
<td abbr="table6.2.3">table6.2.3 cell1</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- table with abbr element -->
|
||||||
|
<table id="table6.3">
|
||||||
|
<tr>
|
||||||
|
<td>table6.3 cell1</td>
|
||||||
|
<td><abbr>table6.3 cell2</abbr></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- table with abbr element having empty text node -->
|
||||||
|
<table id="table6.4">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<abbr>abbr</abbr>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- table with abbr element and non-empty text node -->
|
||||||
|
<table id="table6.5">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
This is a really long text (<abbr>tiarlt</abbr>) inside layout table
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
<!-- layout table with nested table -->
|
<!-- layout table with nested table -->
|
||||||
<table id="table9">
|
<table id="table9">
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>nsIAccessNode util methods testing</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
|
||||||
|
|
||||||
<script type="application/javascript"
|
|
||||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<script type="application/javascript"
|
|
||||||
src="common.js"></script>
|
|
||||||
|
|
||||||
<script type="application/javascript">
|
|
||||||
function doTest()
|
|
||||||
{
|
|
||||||
var elmObj = {};
|
|
||||||
var acc = getAccessible("span", null, elmObj);
|
|
||||||
computedStyle = document.defaultView.getComputedStyle(elmObj.value, "");
|
|
||||||
|
|
||||||
// html:span element
|
|
||||||
is(acc.getComputedStyleValue("", "color"), computedStyle.color,
|
|
||||||
"Wrong color for element with ID 'span'");
|
|
||||||
|
|
||||||
// text child of html:span element
|
|
||||||
acc = getAccessible(acc.firstChild);
|
|
||||||
is(acc.getComputedStyleValue("", "color"), computedStyle.color,
|
|
||||||
"Wrong color for text child of element with ID 'span'");
|
|
||||||
|
|
||||||
SimpleTest.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
addA11yLoadEvent(doTest);
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<a target="_blank"
|
|
||||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=454211"
|
|
||||||
title="nsIAccessNode util methods testing">
|
|
||||||
Mozilla Bug 454211
|
|
||||||
</a>
|
|
||||||
<p id="display"></p>
|
|
||||||
<div id="content" style="display: none"></div>
|
|
||||||
<pre id="test">
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<span role="note" style="color: red" id="span">text</span>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -46,7 +46,7 @@ pref("browser.homescreenURL", "file:///data/local/homescreen.html,file:///system
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// URL for the dialer application.
|
// URL for the dialer application.
|
||||||
pref("dom.telephony.app.phone.url", "http://localhost:7777/data/local/apps/dialer/dialer.html http://localhost:7777/data/local/apps/homescreen/homescreen.html http://localhost:7777/apps/dialer/dialer.html http://localhost:7777/apps/homescreen/homescreen.html");
|
pref("dom.telephony.app.phone.url", "http://localhost:7777/data/local/apps/dialer/dialer.html,http://localhost:7777/data/local/apps/homescreen/homescreen.html,http://localhost:7777/apps/dialer/dialer.html,http://localhost:7777/apps/homescreen/homescreen.html");
|
||||||
|
|
||||||
// Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
|
// Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
|
||||||
pref("browser.viewport.scaleRatio", -1);
|
pref("browser.viewport.scaleRatio", -1);
|
||||||
@@ -444,3 +444,12 @@ pref("power.screen.timeout", 60);
|
|||||||
pref("full-screen-api.enabled", true);
|
pref("full-screen-api.enabled", true);
|
||||||
|
|
||||||
pref("media.volume.steps", 10);
|
pref("media.volume.steps", 10);
|
||||||
|
|
||||||
|
// Data connection settings. These will eventually live in the
|
||||||
|
// navigator.settings API, or even in a database where we can look
|
||||||
|
// it up automatically (bug 729440), but for this will have to do.
|
||||||
|
pref("ril.data.enabled", false);
|
||||||
|
pref("ril.data.roaming.enabled", false);
|
||||||
|
pref("ril.data.apn", "");
|
||||||
|
pref("ril.data.user", "");
|
||||||
|
pref("ril.data.passwd", "");
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ pref("browser.urlbar.doubleClickSelectsAll", true);
|
|||||||
#else
|
#else
|
||||||
pref("browser.urlbar.doubleClickSelectsAll", false);
|
pref("browser.urlbar.doubleClickSelectsAll", false);
|
||||||
#endif
|
#endif
|
||||||
pref("browser.urlbar.autoFill", false);
|
pref("browser.urlbar.autoFill", true);
|
||||||
pref("browser.urlbar.autoFill.typed", true);
|
pref("browser.urlbar.autoFill.typed", true);
|
||||||
// 0: Match anywhere (e.g., middle of words)
|
// 0: Match anywhere (e.g., middle of words)
|
||||||
// 1: Match on word boundaries and then try matching anywhere
|
// 1: Match on word boundaries and then try matching anywhere
|
||||||
@@ -1042,9 +1042,6 @@ pref("devtools.debugger.enabled", false);
|
|||||||
// The default Debugger UI height
|
// The default Debugger UI height
|
||||||
pref("devtools.debugger.ui.height", 250);
|
pref("devtools.debugger.ui.height", 250);
|
||||||
|
|
||||||
// Disable remote debugging protocol logging
|
|
||||||
pref("devtools.debugger.log", false);
|
|
||||||
|
|
||||||
// Enable the style inspector
|
// Enable the style inspector
|
||||||
pref("devtools.styleinspector.enabled", true);
|
pref("devtools.styleinspector.enabled", true);
|
||||||
|
|
||||||
|
|||||||
@@ -440,7 +440,8 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
|||||||
#notification-popup-box[anchorid="geo-notification-icon"] > #geo-notification-icon,
|
#notification-popup-box[anchorid="geo-notification-icon"] > #geo-notification-icon,
|
||||||
#notification-popup-box[anchorid="indexedDB-notification-icon"] > #indexedDB-notification-icon,
|
#notification-popup-box[anchorid="indexedDB-notification-icon"] > #indexedDB-notification-icon,
|
||||||
#notification-popup-box[anchorid="addons-notification-icon"] > #addons-notification-icon,
|
#notification-popup-box[anchorid="addons-notification-icon"] > #addons-notification-icon,
|
||||||
#notification-popup-box[anchorid="password-notification-icon"] > #password-notification-icon {
|
#notification-popup-box[anchorid="password-notification-icon"] > #password-notification-icon,
|
||||||
|
#notification-popup-box[anchorid="webapps-notification-icon"] > #webapps-notification-icon {
|
||||||
display: -moz-box;
|
display: -moz-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4752,10 +4752,15 @@ var XULBrowserWindow = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show or hide browser chrome based on the whitelist
|
// Show or hide browser chrome based on the whitelist
|
||||||
if (this.hideChromeForLocation(location))
|
if (this.hideChromeForLocation(location)) {
|
||||||
document.documentElement.setAttribute("disablechrome", "true");
|
document.documentElement.setAttribute("disablechrome", "true");
|
||||||
else
|
} else {
|
||||||
document.documentElement.removeAttribute("disablechrome");
|
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||||
|
if (ss.getTabValue(gBrowser.selectedTab, "appOrigin"))
|
||||||
|
document.documentElement.setAttribute("disablechrome", "true");
|
||||||
|
else
|
||||||
|
document.documentElement.removeAttribute("disablechrome");
|
||||||
|
}
|
||||||
|
|
||||||
// Disable find commands in documents that ask for them to be disabled.
|
// Disable find commands in documents that ask for them to be disabled.
|
||||||
let disableFind = false;
|
let disableFind = false;
|
||||||
@@ -9100,7 +9105,6 @@ XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
|
|||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
var MousePosTracker = {
|
var MousePosTracker = {
|
||||||
_listeners: [],
|
_listeners: [],
|
||||||
_x: 0,
|
_x: 0,
|
||||||
|
|||||||
@@ -527,6 +527,7 @@
|
|||||||
<image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
|
<image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||||
<image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
|
<image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||||
<image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
|
<image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||||
|
<image id="webapps-notification-icon" class="webapps-anchor-icon" role="button"/>
|
||||||
</box>
|
</box>
|
||||||
<!-- Use onclick instead of normal popup= syntax since the popup
|
<!-- Use onclick instead of normal popup= syntax since the popup
|
||||||
code fires onmousedown, and hence eats our favicon drag events.
|
code fires onmousedown, and hence eats our favicon drag events.
|
||||||
@@ -1003,8 +1004,6 @@
|
|||||||
#endif
|
#endif
|
||||||
<toolbarbutton id="inspector-inspect-toolbutton"
|
<toolbarbutton id="inspector-inspect-toolbutton"
|
||||||
class="devtools-toolbarbutton"
|
class="devtools-toolbarbutton"
|
||||||
label="&inspectButton.label;"
|
|
||||||
accesskey="&inspectButton.accesskey;"
|
|
||||||
command="Inspector:Inspect"/>
|
command="Inspector:Inspect"/>
|
||||||
<toolbarbutton id="inspector-treepanel-toolbutton"
|
<toolbarbutton id="inspector-treepanel-toolbutton"
|
||||||
class="devtools-toolbarbutton"
|
class="devtools-toolbarbutton"
|
||||||
|
|||||||
@@ -87,3 +87,7 @@ html|*#highlighter-nodeinfobar-tagname {
|
|||||||
html|*#highlighter-nodeinfobar-tagname {
|
html|*#highlighter-nodeinfobar-tagname {
|
||||||
text-transform: lowercase;
|
text-transform: lowercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.devtools-toolbarbutton:not([label]) > .toolbarbutton-text {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,16 +15,14 @@ function Cell(aGrid, aNode) {
|
|||||||
this._node._newtabCell = this;
|
this._node._newtabCell = this;
|
||||||
|
|
||||||
// Register drag-and-drop event handlers.
|
// Register drag-and-drop event handlers.
|
||||||
["DragEnter", "DragOver", "DragExit", "Drop"].forEach(function (aType) {
|
["dragenter", "dragover", "dragexit", "drop"].forEach(function (aType) {
|
||||||
let method = "on" + aType;
|
this._node.addEventListener(aType, this, false);
|
||||||
this[method] = this[method].bind(this);
|
|
||||||
this._node.addEventListener(aType.toLowerCase(), this[method], false);
|
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cell.prototype = {
|
Cell.prototype = {
|
||||||
/**
|
/**
|
||||||
*
|
* The grid.
|
||||||
*/
|
*/
|
||||||
_grid: null,
|
_grid: null,
|
||||||
|
|
||||||
@@ -97,41 +95,27 @@ Cell.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for the 'dragenter' event.
|
* Handles all cell events.
|
||||||
* @param aEvent The dragenter event.
|
|
||||||
*/
|
*/
|
||||||
onDragEnter: function Cell_onDragEnter(aEvent) {
|
handleEvent: function Cell_handleEvent(aEvent) {
|
||||||
if (gDrag.isValid(aEvent)) {
|
if (aEvent.type != "dragexit" && !gDrag.isValid(aEvent))
|
||||||
aEvent.preventDefault();
|
return;
|
||||||
gDrop.enter(this, aEvent);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
switch (aEvent.type) {
|
||||||
* Event handler for the 'dragover' event.
|
case "dragenter":
|
||||||
* @param aEvent The dragover event.
|
aEvent.preventDefault();
|
||||||
*/
|
gDrop.enter(this, aEvent);
|
||||||
onDragOver: function Cell_onDragOver(aEvent) {
|
break;
|
||||||
if (gDrag.isValid(aEvent))
|
case "dragover":
|
||||||
aEvent.preventDefault();
|
aEvent.preventDefault();
|
||||||
},
|
break;
|
||||||
|
case "dragexit":
|
||||||
/**
|
gDrop.exit(this, aEvent);
|
||||||
* Event handler for the 'dragexit' event.
|
break;
|
||||||
* @param aEvent The dragexit event.
|
case "drop":
|
||||||
*/
|
aEvent.preventDefault();
|
||||||
onDragExit: function Cell_onDragExit(aEvent) {
|
gDrop.drop(this, aEvent);
|
||||||
gDrop.exit(this, aEvent);
|
break;
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler for the 'drop' event.
|
|
||||||
* @param aEvent The drop event.
|
|
||||||
*/
|
|
||||||
onDrop: function Cell_onDrop(aEvent) {
|
|
||||||
if (gDrag.isValid(aEvent)) {
|
|
||||||
aEvent.preventDefault();
|
|
||||||
gDrop.drop(this, aEvent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,11 +36,11 @@ let gDrag = {
|
|||||||
start: function Drag_start(aSite, aEvent) {
|
start: function Drag_start(aSite, aEvent) {
|
||||||
this._draggedSite = aSite;
|
this._draggedSite = aSite;
|
||||||
|
|
||||||
// Prevent moz-transform for left, top.
|
// Mark nodes as being dragged.
|
||||||
aSite.node.setAttribute("dragged", "true");
|
let selector = ".newtab-site, .newtab-control, .newtab-thumbnail";
|
||||||
|
let nodes = aSite.node.parentNode.querySelectorAll(selector);
|
||||||
// Make sure the dragged site is floating above the grid.
|
for (let i = 0; i < nodes.length; i++)
|
||||||
aSite.node.setAttribute("ontop", "true");
|
nodes[i].setAttribute("dragged", "true");
|
||||||
|
|
||||||
this._setDragData(aSite, aEvent);
|
this._setDragData(aSite, aEvent);
|
||||||
|
|
||||||
@@ -88,13 +88,12 @@ let gDrag = {
|
|||||||
* @param aEvent The 'dragend' event.
|
* @param aEvent The 'dragend' event.
|
||||||
*/
|
*/
|
||||||
end: function Drag_end(aSite, aEvent) {
|
end: function Drag_end(aSite, aEvent) {
|
||||||
aSite.node.removeAttribute("dragged");
|
let nodes = aSite.node.parentNode.querySelectorAll("[dragged]");
|
||||||
|
for (let i = 0; i < nodes.length; i++)
|
||||||
|
nodes[i].removeAttribute("dragged");
|
||||||
|
|
||||||
// Slide the dragged site back into its cell (may be the old or the new cell).
|
// Slide the dragged site back into its cell (may be the old or the new cell).
|
||||||
gTransformation.slideSiteTo(aSite, aSite.cell, {
|
gTransformation.slideSiteTo(aSite, aSite.cell, {unfreeze: true});
|
||||||
unfreeze: true,
|
|
||||||
callback: function () aSite.node.removeAttribute("ontop")
|
|
||||||
});
|
|
||||||
|
|
||||||
this._draggedSite = null;
|
this._draggedSite = null;
|
||||||
},
|
},
|
||||||
@@ -106,7 +105,11 @@ let gDrag = {
|
|||||||
*/
|
*/
|
||||||
isValid: function Drag_isValid(aEvent) {
|
isValid: function Drag_isValid(aEvent) {
|
||||||
let dt = aEvent.dataTransfer;
|
let dt = aEvent.dataTransfer;
|
||||||
return dt && dt.types.contains("text/x-moz-url");
|
let mimeType = "text/x-moz-url";
|
||||||
|
|
||||||
|
// Check that the drag data is non-empty.
|
||||||
|
// Can happen when dragging places folders.
|
||||||
|
return dt && dt.types.contains(mimeType) && dt.getData(mimeType);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,13 +131,13 @@ let gDrag = {
|
|||||||
// Create and use an empty drag element. We don't want to use the default
|
// Create and use an empty drag element. We don't want to use the default
|
||||||
// drag image with its default opacity.
|
// drag image with its default opacity.
|
||||||
let dragElement = document.createElementNS(HTML_NAMESPACE, "div");
|
let dragElement = document.createElementNS(HTML_NAMESPACE, "div");
|
||||||
dragElement.classList.add("drag-element");
|
dragElement.classList.add("newtab-drag");
|
||||||
let body = document.getElementById("body");
|
let scrollbox = document.getElementById("newtab-scrollbox");
|
||||||
body.appendChild(dragElement);
|
scrollbox.appendChild(dragElement);
|
||||||
dt.setDragImage(dragElement, 0, 0);
|
dt.setDragImage(dragElement, 0, 0);
|
||||||
|
|
||||||
// After the 'dragstart' event has been processed we can remove the
|
// After the 'dragstart' event has been processed we can remove the
|
||||||
// temporary drag element from the DOM.
|
// temporary drag element from the DOM.
|
||||||
setTimeout(function () body.removeChild(dragElement), 0);
|
setTimeout(function () scrollbox.removeChild(dragElement), 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,13 +26,26 @@ let gDropTargetShim = {
|
|||||||
init: function DropTargetShim_init() {
|
init: function DropTargetShim_init() {
|
||||||
let node = gGrid.node;
|
let node = gGrid.node;
|
||||||
|
|
||||||
this._dragover = this._dragover.bind(this);
|
|
||||||
|
|
||||||
// Add drag event handlers.
|
// Add drag event handlers.
|
||||||
node.addEventListener("dragstart", this._start.bind(this), true);
|
node.addEventListener("dragstart", this, true);
|
||||||
// XXX bug 505521 - Don't listen for drag, it's useless at the moment.
|
node.addEventListener("dragend", this, true);
|
||||||
//node.addEventListener("drag", this._drag.bind(this), false);
|
},
|
||||||
node.addEventListener("dragend", this._end.bind(this), true);
|
|
||||||
|
/**
|
||||||
|
* Handles all shim events.
|
||||||
|
*/
|
||||||
|
handleEvent: function DropTargetShim_handleEvent(aEvent) {
|
||||||
|
switch (aEvent.type) {
|
||||||
|
case "dragstart":
|
||||||
|
this._start(aEvent);
|
||||||
|
break;
|
||||||
|
case "dragover":
|
||||||
|
this._dragover(aEvent);
|
||||||
|
break;
|
||||||
|
case "dragend":
|
||||||
|
this._end(aEvent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,11 +53,11 @@ let gDropTargetShim = {
|
|||||||
* @param aEvent The 'dragstart' event.
|
* @param aEvent The 'dragstart' event.
|
||||||
*/
|
*/
|
||||||
_start: function DropTargetShim_start(aEvent) {
|
_start: function DropTargetShim_start(aEvent) {
|
||||||
if (aEvent.target.classList.contains("site")) {
|
if (aEvent.target.classList.contains("newtab-link")) {
|
||||||
gGrid.lock();
|
gGrid.lock();
|
||||||
|
|
||||||
// XXX bug 505521 - Listen for dragover on the document.
|
// XXX bug 505521 - Listen for dragover on the document.
|
||||||
document.documentElement.addEventListener("dragover", this._dragover, false);
|
document.documentElement.addEventListener("dragover", this, false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -56,12 +69,7 @@ let gDropTargetShim = {
|
|||||||
// Let's see if we find a drop target.
|
// Let's see if we find a drop target.
|
||||||
let target = this._findDropTarget(aEvent);
|
let target = this._findDropTarget(aEvent);
|
||||||
|
|
||||||
if (target == this._lastDropTarget) {
|
if (target != this._lastDropTarget) {
|
||||||
// XXX bug 505521 - Don't fire dragover for now (causes recursion).
|
|
||||||
/*if (target)
|
|
||||||
// The last drop target is valid and didn't change.
|
|
||||||
this._dispatchEvent(aEvent, "dragover", target);*/
|
|
||||||
} else {
|
|
||||||
if (this._lastDropTarget)
|
if (this._lastDropTarget)
|
||||||
// We left the last drop target.
|
// We left the last drop target.
|
||||||
this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
|
this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
|
||||||
@@ -84,7 +92,7 @@ let gDropTargetShim = {
|
|||||||
* @param aEvent The 'dragover' event.
|
* @param aEvent The 'dragover' event.
|
||||||
*/
|
*/
|
||||||
_dragover: function DropTargetShim_dragover(aEvent) {
|
_dragover: function DropTargetShim_dragover(aEvent) {
|
||||||
let sourceNode = aEvent.dataTransfer.mozSourceNode;
|
let sourceNode = aEvent.dataTransfer.mozSourceNode.parentNode;
|
||||||
gDrag.drag(sourceNode._newtabSite, aEvent);
|
gDrag.drag(sourceNode._newtabSite, aEvent);
|
||||||
|
|
||||||
this._drag(aEvent);
|
this._drag(aEvent);
|
||||||
@@ -117,7 +125,7 @@ let gDropTargetShim = {
|
|||||||
gGrid.unlock();
|
gGrid.unlock();
|
||||||
|
|
||||||
// XXX bug 505521 - Remove the document's dragover listener.
|
// XXX bug 505521 - Remove the document's dragover listener.
|
||||||
document.documentElement.removeEventListener("dragover", this._dragover, false);
|
document.documentElement.removeEventListener("dragover", this, false);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ let gGrid = {
|
|||||||
*/
|
*/
|
||||||
get cells() {
|
get cells() {
|
||||||
let cells = [];
|
let cells = [];
|
||||||
let children = this.node.querySelectorAll("li");
|
let children = this.node.querySelectorAll(".newtab-cell");
|
||||||
for (let i = 0; i < children.length; i++)
|
for (let i = 0; i < children.length; i++)
|
||||||
cells.push(new Cell(this, children[i]));
|
cells.push(new Cell(this, children[i]));
|
||||||
|
|
||||||
@@ -43,8 +43,8 @@ let gGrid = {
|
|||||||
* Initializes the grid.
|
* Initializes the grid.
|
||||||
* @param aSelector The query selector of the grid.
|
* @param aSelector The query selector of the grid.
|
||||||
*/
|
*/
|
||||||
init: function Grid_init(aSelector) {
|
init: function Grid_init() {
|
||||||
this._node = document.querySelector(aSelector);
|
this._node = document.getElementById("newtab-grid");
|
||||||
this._createSiteFragment();
|
this._createSiteFragment();
|
||||||
this._draw();
|
this._draw();
|
||||||
},
|
},
|
||||||
@@ -96,21 +96,20 @@ let gGrid = {
|
|||||||
* Creates the DOM fragment that is re-used when creating sites.
|
* Creates the DOM fragment that is re-used when creating sites.
|
||||||
*/
|
*/
|
||||||
_createSiteFragment: function Grid_createSiteFragment() {
|
_createSiteFragment: function Grid_createSiteFragment() {
|
||||||
let site = document.createElementNS(HTML_NAMESPACE, "a");
|
let site = document.createElementNS(HTML_NAMESPACE, "div");
|
||||||
site.classList.add("site");
|
site.classList.add("newtab-site");
|
||||||
site.setAttribute("draggable", "true");
|
site.setAttribute("draggable", "true");
|
||||||
|
|
||||||
// Create the site's inner HTML code.
|
// Create the site's inner HTML code.
|
||||||
site.innerHTML =
|
site.innerHTML =
|
||||||
'<img class="site-img" width="' + THUMB_WIDTH +'" ' +
|
'<a class="newtab-link">' +
|
||||||
' height="' + THUMB_HEIGHT + '" alt=""/>' +
|
' <span class="newtab-thumbnail"/>' +
|
||||||
'<span class="site-title"/>' +
|
' <span class="newtab-title"/>' +
|
||||||
'<span class="site-strip">' +
|
'</a>' +
|
||||||
' <input class="button strip-button strip-button-pin" type="button"' +
|
'<input type="button" title="' + newTabString("pin") + '"' +
|
||||||
' tabindex="-1" title="' + newTabString("pin") + '"/>' +
|
' class="newtab-control newtab-control-pin"/>' +
|
||||||
' <input class="button strip-button strip-button-block" type="button"' +
|
'<input type="button" title="' + newTabString("block") + '"' +
|
||||||
' tabindex="-1" title="' + newTabString("block") + '"/>' +
|
' class="newtab-control newtab-control-block"/>';
|
||||||
'</span>';
|
|
||||||
|
|
||||||
this._siteFragment = document.createDocumentFragment();
|
this._siteFragment = document.createDocumentFragment();
|
||||||
this._siteFragment.appendChild(site);
|
this._siteFragment.appendChild(site);
|
||||||
|
|||||||
@@ -1,161 +1,174 @@
|
|||||||
:root {
|
:root {
|
||||||
-moz-appearance: none;
|
-moz-user-focus: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
#scrollbox:not([page-disabled]) {
|
input[type=button] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SCROLLBOX */
|
||||||
|
#newtab-scrollbox {
|
||||||
|
display: -moz-box;
|
||||||
|
position: relative;
|
||||||
|
-moz-box-flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newtab-scrollbox:not([page-disabled]) {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#body {
|
/* TOGGLE */
|
||||||
position: relative;
|
#newtab-toggle {
|
||||||
margin: 0;
|
|
||||||
min-width: 675px;
|
|
||||||
-moz-user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TOOLBAR */
|
|
||||||
#toolbar {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
top: 12px;
|
||||||
|
right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#toolbar[page-disabled] {
|
#newtab-toggle:-moz-locale-dir(rtl) {
|
||||||
position: fixed;
|
left: 12px;
|
||||||
}
|
|
||||||
|
|
||||||
#toolbar:-moz-locale-dir(rtl) {
|
|
||||||
left: 8px;
|
|
||||||
right: auto;
|
right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-button {
|
/* MARGINS */
|
||||||
position: absolute;
|
#newtab-vertical-margin {
|
||||||
cursor: pointer;
|
display: -moz-box;
|
||||||
-moz-transition: opacity 200ms ease-out;
|
position: relative;
|
||||||
|
-moz-box-flex: 1;
|
||||||
|
-moz-box-orient: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
#toolbar-button-show,
|
#newtab-margin-top {
|
||||||
#toolbar-button-reset {
|
min-height: 50px;
|
||||||
opacity: 0;
|
max-height: 80px;
|
||||||
pointer-events: none;
|
-moz-box-flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#toolbar-button-reset[modified],
|
#newtab-margin-bottom {
|
||||||
#toolbar-button-show[page-disabled] {
|
min-height: 40px;
|
||||||
opacity: 1;
|
max-height: 100px;
|
||||||
pointer-events: auto;
|
-moz-box-flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#toolbar-button-hide[page-disabled],
|
#newtab-horizontal-margin {
|
||||||
#toolbar-button-reset[page-disabled] {
|
display: -moz-box;
|
||||||
opacity: 0;
|
-moz-box-flex: 5;
|
||||||
pointer-events: none;
|
}
|
||||||
|
|
||||||
|
.newtab-side-margin {
|
||||||
|
min-width: 40px;
|
||||||
|
max-width: 300px;
|
||||||
|
-moz-box-flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GRID */
|
/* GRID */
|
||||||
#grid {
|
#newtab-grid {
|
||||||
width: 637px;
|
display: -moz-box;
|
||||||
height: 411px;
|
-moz-box-flex: 5;
|
||||||
overflow: hidden;
|
-moz-box-orient: vertical;
|
||||||
list-style-type: none;
|
min-width: 600px;
|
||||||
-moz-transition: opacity 200ms ease-out;
|
min-height: 400px;
|
||||||
|
-moz-transition: 100ms ease-out;
|
||||||
|
-moz-transition-property: opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
#grid[page-disabled] {
|
#newtab-grid[page-disabled] {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#grid[page-disabled],
|
#newtab-grid[locked],
|
||||||
#grid[locked] {
|
#newtab-grid[page-disabled] {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ROWS */
|
||||||
|
.newtab-row {
|
||||||
|
display: -moz-box;
|
||||||
|
-moz-box-orient: horizontal;
|
||||||
|
-moz-box-direction: normal;
|
||||||
|
-moz-box-flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* CELLS */
|
/* CELLS */
|
||||||
.cell {
|
.newtab-cell {
|
||||||
float: left;
|
display: -moz-box;
|
||||||
width: 201px;
|
-moz-box-flex: 1;
|
||||||
height: 127px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
-moz-margin-end: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cell:-moz-locale-dir(rtl) {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cell:nth-child(3n+3) {
|
|
||||||
-moz-margin-end: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SITES */
|
/* SITES */
|
||||||
.site {
|
.newtab-site {
|
||||||
display: block;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 201px;
|
-moz-box-flex: 1;
|
||||||
height: 127px;
|
-moz-transition: 100ms ease-out;
|
||||||
|
-moz-transition-property: top, left, opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
.site[frozen] {
|
.newtab-site[frozen] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.site[ontop] {
|
.newtab-site[dragged] {
|
||||||
|
-moz-transition-property: none;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SITE IMAGE */
|
/* LINK + THUMBNAILS */
|
||||||
.site-img {
|
.newtab-link,
|
||||||
display: block;
|
.newtab-thumbnail {
|
||||||
opacity: 0.75;
|
|
||||||
-moz-transition: opacity 200ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.site:hover > .site-img,
|
|
||||||
.site[ontop] > .site-img,
|
|
||||||
.site:-moz-focusring > .site-img {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.site-img[loading] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SITE TITLE */
|
|
||||||
.site-title {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SITE STRIP */
|
|
||||||
.site-strip {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 195px;
|
right: 0;
|
||||||
height: 17px;
|
bottom: 0;
|
||||||
overflow: hidden;
|
|
||||||
opacity: 0;
|
|
||||||
-moz-transition: opacity 200ms ease-out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.site:hover:not([frozen]) > .site-strip {
|
.newtab-thumbnail {
|
||||||
|
opacity: .8;
|
||||||
|
-moz-transition: opacity 100ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newtab-thumbnail[dragged],
|
||||||
|
.newtab-link:-moz-focusring > .newtab-thumbnail,
|
||||||
|
.newtab-site:hover > .newtab-link > .newtab-thumbnail {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.strip-button-pin,
|
/* TITLES */
|
||||||
.strip-button-block:-moz-locale-dir(rtl) {
|
.newtab-title {
|
||||||
float: left;
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.strip-button-block,
|
/* CONTROLS */
|
||||||
.strip-button-pin:-moz-locale-dir(rtl) {
|
.newtab-control {
|
||||||
float: right;
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
opacity: 0;
|
||||||
|
-moz-transition: opacity 100ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newtab-control:-moz-focusring,
|
||||||
|
.newtab-site:hover > .newtab-control {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newtab-control[dragged] {
|
||||||
|
opacity: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newtab-control-pin:-moz-locale-dir(ltr),
|
||||||
|
.newtab-control-block:-moz-locale-dir(rtl) {
|
||||||
|
left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newtab-control-block:-moz-locale-dir(ltr),
|
||||||
|
.newtab-control-pin:-moz-locale-dir(rtl) {
|
||||||
|
right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DRAG & DROP */
|
/* DRAG & DROP */
|
||||||
@@ -165,7 +178,7 @@
|
|||||||
* so that we can use custom drag images and elements. It needs an opacity of
|
* so that we can use custom drag images and elements. It needs an opacity of
|
||||||
* 0.01 so that the core code detects that it's in fact a visible element.
|
* 0.01 so that the core code detects that it's in fact a visible element.
|
||||||
*/
|
*/
|
||||||
.drag-element {
|
.newtab-drag {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|||||||
@@ -30,13 +30,10 @@ XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
|
|||||||
function newTabString(name) gStringBundle.GetStringFromName('newtab.' + name);
|
function newTabString(name) gStringBundle.GetStringFromName('newtab.' + name);
|
||||||
|
|
||||||
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
||||||
const THUMB_WIDTH = 201;
|
|
||||||
const THUMB_HEIGHT = 127;
|
|
||||||
|
|
||||||
#include batch.js
|
#include batch.js
|
||||||
#include transformations.js
|
#include transformations.js
|
||||||
#include page.js
|
#include page.js
|
||||||
#include toolbar.js
|
|
||||||
#include grid.js
|
#include grid.js
|
||||||
#include cells.js
|
#include cells.js
|
||||||
#include sites.js
|
#include sites.js
|
||||||
@@ -47,4 +44,4 @@ const THUMB_HEIGHT = 127;
|
|||||||
#include updater.js
|
#include updater.js
|
||||||
|
|
||||||
// Everything is loaded. Initialize the New Tab Page.
|
// Everything is loaded. Initialize the New Tab Page.
|
||||||
gPage.init("#toolbar", "#grid");
|
gPage.init();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||||
<?xml-stylesheet href="chrome://browser/content/newtab/newTab.css" type="text/css"?>
|
<?xml-stylesheet href="chrome://browser/content/newtab/newTab.css" type="text/css"?>
|
||||||
<?xml-stylesheet href="chrome://browser/skin/newtab/newTab.css" type="text/css"?>
|
<?xml-stylesheet href="chrome://browser/skin/newtab/newTab.css" type="text/css"?>
|
||||||
|
|
||||||
@@ -13,28 +13,44 @@
|
|||||||
%newTabDTD;
|
%newTabDTD;
|
||||||
]>
|
]>
|
||||||
|
|
||||||
<xul:window xmlns="http://www.w3.org/1999/xhtml"
|
<xul:window id="newtab-window" xmlns="http://www.w3.org/1999/xhtml"
|
||||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
disablefastfind="true" title="&newtab.pageTitle;">
|
xul:disablefastfind="true" xul:title="&newtab.pageTitle;">
|
||||||
<xul:vbox id="scrollbox" flex="1" title=" ">
|
|
||||||
<body id="body">
|
<div id="newtab-scrollbox">
|
||||||
<div id="toolbar">
|
|
||||||
<input class="button toolbar-button" id="toolbar-button-show"
|
<div id="newtab-vertical-margin">
|
||||||
type="button" title="&newtab.show;"/>
|
<div id="newtab-margin-top"/>
|
||||||
<input class="button toolbar-button" id="toolbar-button-hide"
|
|
||||||
type="button" title="&newtab.hide;"/>
|
<div id="newtab-horizontal-margin">
|
||||||
<input class="button toolbar-button" id="toolbar-button-reset"
|
<div class="newtab-side-margin"/>
|
||||||
type="button" title="&newtab.reset;"/>
|
|
||||||
|
<div id="newtab-grid">
|
||||||
|
<div class="newtab-row">
|
||||||
|
<div class="newtab-cell"/>
|
||||||
|
<div class="newtab-cell"/>
|
||||||
|
<div class="newtab-cell"/>
|
||||||
|
</div>
|
||||||
|
<div class="newtab-row">
|
||||||
|
<div class="newtab-cell"/>
|
||||||
|
<div class="newtab-cell"/>
|
||||||
|
<div class="newtab-cell"/>
|
||||||
|
</div>
|
||||||
|
<div class="newtab-row">
|
||||||
|
<div class="newtab-cell"/>
|
||||||
|
<div class="newtab-cell"/>
|
||||||
|
<div class="newtab-cell"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="newtab-side-margin"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul id="grid">
|
<div id="newtab-margin-bottom"/>
|
||||||
<li class="cell"/><li class="cell"/><li class="cell"/>
|
</div>
|
||||||
<li class="cell"/><li class="cell"/><li class="cell"/>
|
<input id="newtab-toggle" type="button"/>
|
||||||
<li class="cell"/><li class="cell"/><li class="cell"/>
|
</div>
|
||||||
</ul>
|
|
||||||
|
|
||||||
<xul:script type="text/javascript;version=1.8"
|
<xul:script type="text/javascript;version=1.8"
|
||||||
src="chrome://browser/content/newtab/newTab.js"/>
|
src="chrome://browser/content/newtab/newTab.js"/>
|
||||||
</body>
|
|
||||||
</xul:vbox>
|
|
||||||
</xul:window>
|
</xul:window>
|
||||||
|
|||||||
@@ -11,25 +11,24 @@
|
|||||||
let gPage = {
|
let gPage = {
|
||||||
/**
|
/**
|
||||||
* Initializes the page.
|
* Initializes the page.
|
||||||
* @param aToolbarSelector The query selector for the page toolbar.
|
|
||||||
* @param aGridSelector The query selector for the grid.
|
|
||||||
*/
|
*/
|
||||||
init: function Page_init(aToolbarSelector, aGridSelector) {
|
init: function Page_init() {
|
||||||
gToolbar.init(aToolbarSelector);
|
|
||||||
this._gridSelector = aGridSelector;
|
|
||||||
|
|
||||||
// Add ourselves to the list of pages to receive notifications.
|
// Add ourselves to the list of pages to receive notifications.
|
||||||
gAllPages.register(this);
|
gAllPages.register(this);
|
||||||
|
|
||||||
// Listen for 'unload' to unregister this page.
|
// Listen for 'unload' to unregister this page.
|
||||||
function unload() { gAllPages.unregister(this); }
|
addEventListener("unload", this, false);
|
||||||
addEventListener("unload", unload.bind(this), false);
|
|
||||||
|
// Listen for toggle button clicks.
|
||||||
|
let button = document.getElementById("newtab-toggle");
|
||||||
|
button.addEventListener("click", this, false);
|
||||||
|
|
||||||
// Check if the new tab feature is enabled.
|
// Check if the new tab feature is enabled.
|
||||||
if (gAllPages.enabled)
|
let enabled = gAllPages.enabled;
|
||||||
|
if (enabled)
|
||||||
this._init();
|
this._init();
|
||||||
else
|
|
||||||
this._updateAttributes(false);
|
this._updateAttributes(enabled);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,25 +47,9 @@ let gPage = {
|
|||||||
* Updates the whole page and the grid when the storage has changed.
|
* Updates the whole page and the grid when the storage has changed.
|
||||||
*/
|
*/
|
||||||
update: function Page_update() {
|
update: function Page_update() {
|
||||||
this.updateModifiedFlag();
|
|
||||||
gGrid.refresh();
|
gGrid.refresh();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the page is modified and sets the CSS class accordingly
|
|
||||||
*/
|
|
||||||
updateModifiedFlag: function Page_updateModifiedFlag() {
|
|
||||||
let node = document.getElementById("toolbar-button-reset");
|
|
||||||
let modified = this._isModified();
|
|
||||||
|
|
||||||
if (modified)
|
|
||||||
node.setAttribute("modified", "true");
|
|
||||||
else
|
|
||||||
node.removeAttribute("modified");
|
|
||||||
|
|
||||||
this._updateTabIndices(gAllPages.enabled, modified);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internally initializes the page. This runs only when/if the feature
|
* Internally initializes the page. This runs only when/if the feature
|
||||||
* is/gets enabled.
|
* is/gets enabled.
|
||||||
@@ -78,29 +61,27 @@ let gPage = {
|
|||||||
this._initialized = true;
|
this._initialized = true;
|
||||||
|
|
||||||
gLinks.populateCache(function () {
|
gLinks.populateCache(function () {
|
||||||
// Check if the grid is modified.
|
|
||||||
this.updateModifiedFlag();
|
|
||||||
|
|
||||||
// Initialize and render the grid.
|
// Initialize and render the grid.
|
||||||
gGrid.init(this._gridSelector);
|
gGrid.init();
|
||||||
|
|
||||||
// Initialize the drop target shim.
|
// Initialize the drop target shim.
|
||||||
gDropTargetShim.init();
|
gDropTargetShim.init();
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
// Workaround to prevent a delay on MacOSX due to a slow drop animation.
|
// Workaround to prevent a delay on MacOSX due to a slow drop animation.
|
||||||
document.addEventListener("dragover", this.onDragOver, false);
|
document.addEventListener("dragover", this, false);
|
||||||
document.addEventListener("drop", this.onDrop, false);
|
document.addEventListener("drop", this, false);
|
||||||
#endif
|
#endif
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the 'page-disabled' attributes of the respective DOM nodes.
|
* Updates the 'page-disabled' attributes of the respective DOM nodes.
|
||||||
* @param aValue Whether to set or remove attributes.
|
* @param aValue Whether the New Tab Page is enabled or not.
|
||||||
*/
|
*/
|
||||||
_updateAttributes: function Page_updateAttributes(aValue) {
|
_updateAttributes: function Page_updateAttributes(aValue) {
|
||||||
let nodes = document.querySelectorAll("#grid, #scrollbox, #toolbar, .toolbar-button");
|
let selector = "#newtab-scrollbox, #newtab-toggle, #newtab-grid";
|
||||||
|
let nodes = document.querySelectorAll(selector);
|
||||||
|
|
||||||
// Set the nodes' states.
|
// Set the nodes' states.
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
@@ -111,64 +92,32 @@ let gPage = {
|
|||||||
node.setAttribute("page-disabled", "true");
|
node.setAttribute("page-disabled", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
this._updateTabIndices(aValue, this._isModified());
|
// Update the toggle button's title.
|
||||||
|
let toggle = document.getElementById("newtab-toggle");
|
||||||
|
toggle.setAttribute("title", newTabString(aValue ? "hide" : "show"));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the page is modified.
|
* Handles all page events.
|
||||||
* @return Whether the page is modified or not.
|
|
||||||
*/
|
*/
|
||||||
_isModified: function Page_isModified() {
|
handleEvent: function Page_handleEvent(aEvent) {
|
||||||
// The page is considered modified only if sites have been removed.
|
switch (aEvent.type) {
|
||||||
return !gBlockedLinks.isEmpty();
|
case "unload":
|
||||||
},
|
gAllPages.unregister(this);
|
||||||
|
break;
|
||||||
/**
|
case "click":
|
||||||
* Updates the tab indices of focusable elements.
|
gAllPages.enabled = !gAllPages.enabled;
|
||||||
* @param aEnabled Whether the page is currently enabled.
|
break;
|
||||||
* @param aModified Whether the page is currently modified.
|
case "dragover":
|
||||||
*/
|
if (gDrag.isValid(aEvent) && gDrag.draggedSite)
|
||||||
_updateTabIndices: function Page_updateTabIndices(aEnabled, aModified) {
|
aEvent.preventDefault();
|
||||||
function setFocusable(aNode, aFocusable) {
|
break;
|
||||||
if (aFocusable)
|
case "drop":
|
||||||
aNode.removeAttribute("tabindex");
|
if (gDrag.isValid(aEvent) && gDrag.draggedSite) {
|
||||||
else
|
aEvent.preventDefault();
|
||||||
aNode.setAttribute("tabindex", "-1");
|
aEvent.stopPropagation();
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
// Sites and the 'hide' button are always focusable when the grid is shown.
|
|
||||||
let nodes = document.querySelectorAll(".site, #toolbar-button-hide");
|
|
||||||
for (let i = 0; i < nodes.length; i++)
|
|
||||||
setFocusable(nodes[i], aEnabled);
|
|
||||||
|
|
||||||
// The 'show' button is focusable when the grid is hidden.
|
|
||||||
let btnShow = document.getElementById("toolbar-button-show");
|
|
||||||
setFocusable(btnShow, !aEnabled);
|
|
||||||
|
|
||||||
// The 'reset' button is focusable when the grid is shown and modified.
|
|
||||||
let btnReset = document.getElementById("toolbar-button-reset");
|
|
||||||
setFocusable(btnReset, aEnabled && aModified);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the 'dragover' event. Workaround to prevent a delay on MacOSX
|
|
||||||
* due to a slow drop animation.
|
|
||||||
* @param aEvent The 'dragover' event.
|
|
||||||
*/
|
|
||||||
onDragOver: function Page_onDragOver(aEvent) {
|
|
||||||
if (gDrag.isValid(aEvent) && gDrag.draggedSite)
|
|
||||||
aEvent.preventDefault();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the 'drop' event. Workaround to prevent a delay on MacOSX due to
|
|
||||||
* a slow drop animation.
|
|
||||||
* @param aEvent The 'drop' event.
|
|
||||||
*/
|
|
||||||
onDrop: function Page_onDrop(aEvent) {
|
|
||||||
if (gDrag.isValid(aEvent) && gDrag.draggedSite) {
|
|
||||||
aEvent.preventDefault();
|
|
||||||
aEvent.stopPropagation();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -82,12 +82,16 @@ Site.prototype = {
|
|||||||
/**
|
/**
|
||||||
* Blocks the site (removes it from the grid) and calls the given callback
|
* Blocks the site (removes it from the grid) and calls the given callback
|
||||||
* when done.
|
* when done.
|
||||||
* @param aCallback The callback to be called when finished.
|
* @param aCallback The function to be called when finished.
|
||||||
*/
|
*/
|
||||||
block: function Site_block(aCallback) {
|
block: function Site_block(aCallback) {
|
||||||
gBlockedLinks.block(this._link);
|
if (gBlockedLinks.isBlocked(this._link)) {
|
||||||
gUpdater.updateGrid(aCallback);
|
if (aCallback)
|
||||||
gPage.updateModifiedFlag();
|
aCallback();
|
||||||
|
} else {
|
||||||
|
gBlockedLinks.block(this._link);
|
||||||
|
gUpdater.updateGrid(aCallback);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,14 +109,14 @@ Site.prototype = {
|
|||||||
* @param aPinned Whether this site is now pinned or unpinned.
|
* @param aPinned Whether this site is now pinned or unpinned.
|
||||||
*/
|
*/
|
||||||
_updateAttributes: function (aPinned) {
|
_updateAttributes: function (aPinned) {
|
||||||
let buttonPin = this._querySelector(".strip-button-pin");
|
let control = this._querySelector(".newtab-control-pin");
|
||||||
|
|
||||||
if (aPinned) {
|
if (aPinned) {
|
||||||
this.node.setAttribute("pinned", true);
|
control.setAttribute("pinned", true);
|
||||||
buttonPin.setAttribute("title", newTabString("unpin"));
|
control.setAttribute("title", newTabString("unpin"));
|
||||||
} else {
|
} else {
|
||||||
this.node.removeAttribute("pinned");
|
control.removeAttribute("pinned");
|
||||||
buttonPin.setAttribute("title", newTabString("pin"));
|
control.setAttribute("title", newTabString("pin"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -121,32 +125,17 @@ Site.prototype = {
|
|||||||
*/
|
*/
|
||||||
_render: function Site_render() {
|
_render: function Site_render() {
|
||||||
let title = this.title || this.url;
|
let title = this.title || this.url;
|
||||||
this.node.setAttribute("title", title);
|
let link = this._querySelector(".newtab-link");
|
||||||
this.node.setAttribute("href", this.url);
|
link.setAttribute("title", title);
|
||||||
this._querySelector(".site-title").textContent = title;
|
link.setAttribute("href", this.url);
|
||||||
|
this._querySelector(".newtab-title").textContent = title;
|
||||||
|
|
||||||
if (this.isPinned())
|
if (this.isPinned())
|
||||||
this._updateAttributes(true);
|
this._updateAttributes(true);
|
||||||
|
|
||||||
this._renderThumbnail();
|
let thumbnailURL = PageThumbs.getThumbnailURL(this.url);
|
||||||
},
|
let thumbnail = this._querySelector(".newtab-thumbnail");
|
||||||
|
thumbnail.style.backgroundImage = "url(" + thumbnailURL + ")";
|
||||||
/**
|
|
||||||
* Renders the site's thumbnail.
|
|
||||||
*/
|
|
||||||
_renderThumbnail: function Site_renderThumbnail() {
|
|
||||||
let img = this._querySelector(".site-img")
|
|
||||||
img.setAttribute("alt", this.title || this.url);
|
|
||||||
img.setAttribute("loading", "true");
|
|
||||||
|
|
||||||
// Wait until the image has loaded.
|
|
||||||
img.addEventListener("load", function onLoad() {
|
|
||||||
img.removeEventListener("load", onLoad, false);
|
|
||||||
img.removeAttribute("loading");
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
// Set the thumbnail url.
|
|
||||||
img.setAttribute("src", PageThumbs.getThumbnailURL(this.url));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,56 +143,37 @@ Site.prototype = {
|
|||||||
*/
|
*/
|
||||||
_addEventHandlers: function Site_addEventHandlers() {
|
_addEventHandlers: function Site_addEventHandlers() {
|
||||||
// Register drag-and-drop event handlers.
|
// Register drag-and-drop event handlers.
|
||||||
["DragStart", /*"Drag",*/ "DragEnd"].forEach(function (aType) {
|
this._node.addEventListener("dragstart", this, false);
|
||||||
let method = "_on" + aType;
|
this._node.addEventListener("dragend", this, false);
|
||||||
this[method] = this[method].bind(this);
|
|
||||||
this._node.addEventListener(aType.toLowerCase(), this[method], false);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
let self = this;
|
let controls = this.node.querySelectorAll(".newtab-control");
|
||||||
|
for (let i = 0; i < controls.length; i++)
|
||||||
function pin(aEvent) {
|
controls[i].addEventListener("click", this, false);
|
||||||
if (aEvent)
|
|
||||||
aEvent.preventDefault();
|
|
||||||
|
|
||||||
if (self.isPinned())
|
|
||||||
self.unpin();
|
|
||||||
else
|
|
||||||
self.pin();
|
|
||||||
}
|
|
||||||
|
|
||||||
function block(aEvent) {
|
|
||||||
if (aEvent)
|
|
||||||
aEvent.preventDefault();
|
|
||||||
|
|
||||||
self.block();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._querySelector(".strip-button-pin").addEventListener("click", pin, false);
|
|
||||||
this._querySelector(".strip-button-block").addEventListener("click", block, false);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for the 'dragstart' event.
|
* Handles all site events.
|
||||||
* @param aEvent The drag event.
|
|
||||||
*/
|
*/
|
||||||
_onDragStart: function Site_onDragStart(aEvent) {
|
handleEvent: function Site_handleEvent(aEvent) {
|
||||||
gDrag.start(this, aEvent);
|
switch (aEvent.type) {
|
||||||
},
|
case "click":
|
||||||
|
aEvent.preventDefault();
|
||||||
/**
|
if (aEvent.target.classList.contains("newtab-control-block"))
|
||||||
* Event handler for the 'drag' event.
|
this.block();
|
||||||
* @param aEvent The drag event.
|
else if (this.isPinned())
|
||||||
*/
|
this.unpin();
|
||||||
_onDrag: function Site_onDrag(aEvent) {
|
else
|
||||||
gDrag.drag(this, aEvent);
|
this.pin();
|
||||||
},
|
break;
|
||||||
|
case "dragstart":
|
||||||
/**
|
gDrag.start(this, aEvent);
|
||||||
* Event handler for the 'dragend' event.
|
break;
|
||||||
* @param aEvent The drag event.
|
case "drag":
|
||||||
*/
|
gDrag.drag(this, aEvent);
|
||||||
_onDragEnd: function Site_onDragEnd(aEvent) {
|
break;
|
||||||
gDrag.end(this, aEvent);
|
case "dragend":
|
||||||
|
gDrag.end(this, aEvent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
#ifdef 0
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This singleton represents the page's toolbar that allows to enable/disable
|
|
||||||
* the 'New Tab Page' feature and to reset the whole page.
|
|
||||||
*/
|
|
||||||
let gToolbar = {
|
|
||||||
/**
|
|
||||||
* Initializes the toolbar.
|
|
||||||
* @param aSelector The query selector of the toolbar.
|
|
||||||
*/
|
|
||||||
init: function Toolbar_init(aSelector) {
|
|
||||||
this._node = document.querySelector(aSelector);
|
|
||||||
let buttons = this._node.querySelectorAll("input");
|
|
||||||
|
|
||||||
// Listen for 'click' events on the toolbar buttons.
|
|
||||||
["show", "hide", "reset"].forEach(function (aType, aIndex) {
|
|
||||||
let self = this;
|
|
||||||
let button = buttons[aIndex];
|
|
||||||
let handler = function () self[aType]();
|
|
||||||
|
|
||||||
button.addEventListener("click", handler, false);
|
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
|
||||||
// Per default buttons lose focus after being clicked on Mac OS X.
|
|
||||||
// So when the URL bar has focus and a toolbar button is clicked the
|
|
||||||
// URL bar regains focus and the history pops up. We need to prevent
|
|
||||||
// that by explicitly removing its focus.
|
|
||||||
button.addEventListener("mousedown", function () {
|
|
||||||
window.focus();
|
|
||||||
}, false);
|
|
||||||
#endif
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables the 'New Tab Page' feature.
|
|
||||||
*/
|
|
||||||
show: function Toolbar_show() {
|
|
||||||
this._passButtonFocus("show", "hide");
|
|
||||||
gAllPages.enabled = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables the 'New Tab Page' feature.
|
|
||||||
*/
|
|
||||||
hide: function Toolbar_hide() {
|
|
||||||
this._passButtonFocus("hide", "show");
|
|
||||||
gAllPages.enabled = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the whole page and forces it to re-render its content.
|
|
||||||
* @param aCallback The callback to call when the page has been reset.
|
|
||||||
*/
|
|
||||||
reset: function Toolbar_reset(aCallback) {
|
|
||||||
this._passButtonFocus("reset", "hide");
|
|
||||||
let node = gGrid.node;
|
|
||||||
|
|
||||||
// animate the page reset
|
|
||||||
gTransformation.fadeNodeOut(node, function () {
|
|
||||||
NewTabUtils.reset();
|
|
||||||
|
|
||||||
gLinks.populateCache(function () {
|
|
||||||
gAllPages.update();
|
|
||||||
|
|
||||||
// Without the setTimeout() we have a strange flicker.
|
|
||||||
setTimeout(function () gTransformation.fadeNodeIn(node, aCallback));
|
|
||||||
}, true);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Passes the focus from the current button to the next.
|
|
||||||
* @param aCurrent The button that currently has focus.
|
|
||||||
* @param aNext The button that is focused next.
|
|
||||||
*/
|
|
||||||
_passButtonFocus: function Toolbar_passButtonFocus(aCurrent, aNext) {
|
|
||||||
if (document.querySelector("#toolbar-button-" + aCurrent + ":-moz-focusring"))
|
|
||||||
document.getElementById("toolbar-button-" + aNext).focus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -10,6 +10,24 @@
|
|||||||
* convenience methods to work with a site's DOM node.
|
* convenience methods to work with a site's DOM node.
|
||||||
*/
|
*/
|
||||||
let gTransformation = {
|
let gTransformation = {
|
||||||
|
/**
|
||||||
|
* Returns the width of the left and top border of a cell. We need to take it
|
||||||
|
* into account when measuring and comparing site and cell positions.
|
||||||
|
*/
|
||||||
|
get _cellBorderWidths() {
|
||||||
|
let cstyle = window.getComputedStyle(gGrid.cells[0].node, null);
|
||||||
|
let widths = {
|
||||||
|
left: parseInt(cstyle.getPropertyValue("border-left-width")),
|
||||||
|
top: parseInt(cstyle.getPropertyValue("border-top-width"))
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cache this value, overwrite the getter.
|
||||||
|
Object.defineProperty(this, "_cellBorderWidths",
|
||||||
|
{value: widths, enumerable: true});
|
||||||
|
|
||||||
|
return widths;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a DOM node's position.
|
* Gets a DOM node's position.
|
||||||
* @param aNode The DOM node.
|
* @param aNode The DOM node.
|
||||||
@@ -80,6 +98,14 @@ let gTransformation = {
|
|||||||
* @param aSite The site to freeze.
|
* @param aSite The site to freeze.
|
||||||
*/
|
*/
|
||||||
freezeSitePosition: function Transformation_freezeSitePosition(aSite) {
|
freezeSitePosition: function Transformation_freezeSitePosition(aSite) {
|
||||||
|
if (this._isFrozen(aSite))
|
||||||
|
return;
|
||||||
|
|
||||||
|
let style = aSite.node.style;
|
||||||
|
let comp = getComputedStyle(aSite.node, null);
|
||||||
|
style.width = comp.getPropertyValue("width")
|
||||||
|
style.height = comp.getPropertyValue("height");
|
||||||
|
|
||||||
aSite.node.setAttribute("frozen", "true");
|
aSite.node.setAttribute("frozen", "true");
|
||||||
this.setSitePosition(aSite, this.getNodePosition(aSite.node));
|
this.setSitePosition(aSite, this.getNodePosition(aSite.node));
|
||||||
},
|
},
|
||||||
@@ -89,8 +115,11 @@ let gTransformation = {
|
|||||||
* @param aSite The site to unfreeze.
|
* @param aSite The site to unfreeze.
|
||||||
*/
|
*/
|
||||||
unfreezeSitePosition: function Transformation_unfreezeSitePosition(aSite) {
|
unfreezeSitePosition: function Transformation_unfreezeSitePosition(aSite) {
|
||||||
|
if (!this._isFrozen(aSite))
|
||||||
|
return;
|
||||||
|
|
||||||
let style = aSite.node.style;
|
let style = aSite.node.style;
|
||||||
style.left = style.top = "";
|
style.left = style.top = style.width = style.height = "";
|
||||||
aSite.node.removeAttribute("frozen");
|
aSite.node.removeAttribute("frozen");
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -117,8 +146,13 @@ let gTransformation = {
|
|||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need to take the width of a cell's border into account.
|
||||||
|
targetPosition.left += this._cellBorderWidths.left;
|
||||||
|
targetPosition.top += this._cellBorderWidths.top;
|
||||||
|
|
||||||
// Nothing to do here if the positions already match.
|
// Nothing to do here if the positions already match.
|
||||||
if (currentPosition.equals(targetPosition)) {
|
if (currentPosition.left == targetPosition.left &&
|
||||||
|
currentPosition.top == targetPosition.top) {
|
||||||
finish();
|
finish();
|
||||||
} else {
|
} else {
|
||||||
this.setSitePosition(aSite, targetPosition);
|
this.setSitePosition(aSite, targetPosition);
|
||||||
@@ -222,5 +256,14 @@ let gTransformation = {
|
|||||||
_moveSite: function Transformation_moveSite(aSite, aIndex, aOptions) {
|
_moveSite: function Transformation_moveSite(aSite, aIndex, aOptions) {
|
||||||
this.freezeSitePosition(aSite);
|
this.freezeSitePosition(aSite);
|
||||||
this.slideSiteTo(aSite, gGrid.cells[aIndex], aOptions);
|
this.slideSiteTo(aSite, gGrid.cells[aIndex], aOptions);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a site is currently frozen.
|
||||||
|
* @param aSite The site to check.
|
||||||
|
* @return Whether the given site is frozen.
|
||||||
|
*/
|
||||||
|
_isFrozen: function Transformation_isFrozen(aSite) {
|
||||||
|
return aSite.node.hasAttribute("frozen");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ _BROWSER_FILES = \
|
|||||||
browser_newtab_bug722273.js \
|
browser_newtab_bug722273.js \
|
||||||
browser_newtab_bug723102.js \
|
browser_newtab_bug723102.js \
|
||||||
browser_newtab_bug723121.js \
|
browser_newtab_bug723121.js \
|
||||||
|
browser_newtab_bug725996.js \
|
||||||
|
browser_newtab_bug734043.js \
|
||||||
head.js \
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ function runTests() {
|
|||||||
yield addNewTabPageTab();
|
yield addNewTabPageTab();
|
||||||
gBrowser.removeTab(firstTab);
|
gBrowser.removeTab(firstTab);
|
||||||
|
|
||||||
cw.gToolbar.hide();
|
ok(NewTabUtils.allPages.enabled, true, "page is enabled");
|
||||||
|
NewTabUtils.allPages.enabled = false;
|
||||||
ok(cw.gGrid.node.hasAttribute("page-disabled"), "page is disabled");
|
ok(cw.gGrid.node.hasAttribute("page-disabled"), "page is disabled");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,19 @@ function runTests() {
|
|||||||
|
|
||||||
let cell = cells[0].node;
|
let cell = cells[0].node;
|
||||||
let site = cells[0].site.node;
|
let site = cells[0].site.node;
|
||||||
|
let link = site.querySelector(".newtab-link");
|
||||||
|
|
||||||
sendDragEvent(site, "dragstart");
|
sendDragEvent(link, "dragstart");
|
||||||
checkGridLocked(true, "grid is now locked");
|
checkGridLocked(true, "grid is now locked");
|
||||||
|
|
||||||
sendDragEvent(site, "dragend");
|
sendDragEvent(link, "dragend");
|
||||||
checkGridLocked(false, "grid isn't locked anymore");
|
checkGridLocked(false, "grid isn't locked anymore");
|
||||||
|
|
||||||
sendDragEvent(cell, "dragstart");
|
sendDragEvent(cell, "dragstart");
|
||||||
checkGridLocked(false, "grid isn't locked - dragstart was ignored");
|
checkGridLocked(false, "grid isn't locked - dragstart was ignored");
|
||||||
|
|
||||||
|
sendDragEvent(site, "dragstart");
|
||||||
|
checkGridLocked(false, "grid isn't locked - dragstart was ignored");
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkGridLocked(aLocked, aMessage) {
|
function checkGridLocked(aLocked, aMessage) {
|
||||||
|
|||||||
52
browser/base/content/test/newtab/browser_newtab_bug725996.js
Normal file
52
browser/base/content/test/newtab/browser_newtab_bug725996.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
setLinks("0,1,2,3,4,5,6,7,8");
|
||||||
|
setPinnedLinks("");
|
||||||
|
|
||||||
|
yield addNewTabPageTab();
|
||||||
|
checkGrid("0,1,2,3,4,5,6,7,8");
|
||||||
|
|
||||||
|
let cell = cells[0].node;
|
||||||
|
|
||||||
|
sendDropEvent(cell, "about:blank#99\nblank");
|
||||||
|
is(NewTabUtils.pinnedLinks.links[0].url, "about:blank#99",
|
||||||
|
"first cell is pinned and contains the dropped site");
|
||||||
|
|
||||||
|
yield whenPagesUpdated();
|
||||||
|
checkGrid("99p,0,1,2,3,4,5,6,7");
|
||||||
|
|
||||||
|
sendDropEvent(cell, "");
|
||||||
|
is(NewTabUtils.pinnedLinks.links[0].url, "about:blank#99",
|
||||||
|
"first cell is still pinned with the site we dropped before");
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendDropEvent(aNode, aData) {
|
||||||
|
let ifaceReq = cw.QueryInterface(Ci.nsIInterfaceRequestor);
|
||||||
|
let windowUtils = ifaceReq.getInterface(Ci.nsIDOMWindowUtils);
|
||||||
|
|
||||||
|
let dataTransfer = {
|
||||||
|
mozUserCancelled: false,
|
||||||
|
setData: function () null,
|
||||||
|
setDragImage: function () null,
|
||||||
|
getData: function () aData,
|
||||||
|
|
||||||
|
types: {
|
||||||
|
contains: function (aType) aType == "text/x-moz-url"
|
||||||
|
},
|
||||||
|
|
||||||
|
mozGetDataAt: function (aType, aIndex) {
|
||||||
|
if (aIndex || aType != "text/x-moz-url")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return aData;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let event = cw.document.createEvent("DragEvents");
|
||||||
|
event.initDragEvent("drop", true, true, cw, 0, 0, 0, 0, 0,
|
||||||
|
false, false, false, false, 0, null, dataTransfer);
|
||||||
|
|
||||||
|
windowUtils.dispatchDOMEventViaPresShell(aNode, event, true);
|
||||||
|
}
|
||||||
30
browser/base/content/test/newtab/browser_newtab_bug734043.js
Normal file
30
browser/base/content/test/newtab/browser_newtab_bug734043.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
// TODO Bug 735166 - Intermittent timeout in browser_newtab_bug734043.js
|
||||||
|
return;
|
||||||
|
|
||||||
|
setLinks("0,1,2,3,4,5,6,7,8");
|
||||||
|
setPinnedLinks("");
|
||||||
|
|
||||||
|
yield addNewTabPageTab();
|
||||||
|
|
||||||
|
let receivedError = false;
|
||||||
|
let block = cw.document.querySelector(".newtab-control-block");
|
||||||
|
|
||||||
|
function onError() {
|
||||||
|
receivedError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw.addEventListener("error", onError);
|
||||||
|
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
EventUtils.synthesizeMouseAtCenter(block, {}, cw);
|
||||||
|
yield executeSoon(TestRunner.next);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield whenPagesUpdated();
|
||||||
|
ok(!receivedError, "we got here without any errors");
|
||||||
|
cw.removeEventListener("error", onError);
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ function runTests() {
|
|||||||
|
|
||||||
ok(!gridNode.hasAttribute("page-disabled"), "page is not disabled");
|
ok(!gridNode.hasAttribute("page-disabled"), "page is not disabled");
|
||||||
|
|
||||||
cw.gToolbar.hide();
|
NewTabUtils.allPages.enabled = false;
|
||||||
ok(gridNode.hasAttribute("page-disabled"), "page is disabled");
|
ok(gridNode.hasAttribute("page-disabled"), "page is disabled");
|
||||||
|
|
||||||
let oldGridNode = cw.gGrid.node;
|
let oldGridNode = cw.gGrid.node;
|
||||||
@@ -28,7 +28,7 @@ function runTests() {
|
|||||||
// check that no sites have been rendered
|
// check that no sites have been rendered
|
||||||
is(0, cw.document.querySelectorAll(".site").length, "no sites have been rendered");
|
is(0, cw.document.querySelectorAll(".site").length, "no sites have been rendered");
|
||||||
|
|
||||||
cw.gToolbar.show();
|
NewTabUtils.allPages.enabled = true;
|
||||||
ok(!gridNode.hasAttribute("page-disabled"), "page is not disabled");
|
ok(!gridNode.hasAttribute("page-disabled"), "page is not disabled");
|
||||||
ok(!oldGridNode.hasAttribute("page-disabled"), "old page is not disabled");
|
ok(!oldGridNode.hasAttribute("page-disabled"), "old page is not disabled");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
* These tests make sure that resetting the 'New Tage Page' works as expected.
|
* These tests make sure that resetting the 'New Tage Page' works as expected.
|
||||||
*/
|
*/
|
||||||
function runTests() {
|
function runTests() {
|
||||||
|
// Disabled until bug 716543 is fixed.
|
||||||
|
return;
|
||||||
|
|
||||||
// create a new tab page and check its modified state after blocking a site
|
// create a new tab page and check its modified state after blocking a site
|
||||||
setLinks("0,1,2,3,4,5,6,7,8");
|
setLinks("0,1,2,3,4,5,6,7,8");
|
||||||
setPinnedLinks("");
|
setPinnedLinks("");
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
* state.
|
* state.
|
||||||
*/
|
*/
|
||||||
function runTests() {
|
function runTests() {
|
||||||
|
// Disabled until bug 716543 is fixed.
|
||||||
|
return;
|
||||||
|
|
||||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||||
setPinnedLinks(",1");
|
setPinnedLinks(",1");
|
||||||
|
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ function checkGrid(aSitesPattern, aSites) {
|
|||||||
|
|
||||||
let shouldBePinned = /p$/.test(id);
|
let shouldBePinned = /p$/.test(id);
|
||||||
let cellContainsPinned = site.isPinned();
|
let cellContainsPinned = site.isPinned();
|
||||||
let cssClassPinned = site.node && site.node.hasAttribute("pinned");
|
let cssClassPinned = site.node && site.node.querySelector(".newtab-control-pin").hasAttribute("pinned");
|
||||||
|
|
||||||
// Check if the site should be and is pinned.
|
// Check if the site should be and is pinned.
|
||||||
if (shouldBePinned) {
|
if (shouldBePinned) {
|
||||||
@@ -265,3 +265,20 @@ function simulateDrop(aDropTarget, aDragSource) {
|
|||||||
if (aDragSource)
|
if (aDragSource)
|
||||||
cw.gDrag.end(aDragSource.site);
|
cw.gDrag.end(aDragSource.site);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumes testing when all pages have been updated.
|
||||||
|
*/
|
||||||
|
function whenPagesUpdated() {
|
||||||
|
let page = {
|
||||||
|
update: function () {
|
||||||
|
NewTabUtils.allPages.unregister(this);
|
||||||
|
executeSoon(TestRunner.next);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NewTabUtils.allPages.register(page);
|
||||||
|
registerCleanupFunction(function () {
|
||||||
|
NewTabUtils.allPages.unregister(page);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,7 +44,23 @@ Components.utils.import("resource://gre/modules/Services.jsm");
|
|||||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () {
|
XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () {
|
||||||
return Services.prefs.getCharPref("browser.newtab.url") || "about:blank";
|
const PREF = "browser.newtab.url";
|
||||||
|
|
||||||
|
function getNewTabPageURL() {
|
||||||
|
return Services.prefs.getCharPref(PREF) || "about:blank";
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
BROWSER_NEW_TAB_URL = getNewTabPageURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.prefs.addObserver(PREF, update, false);
|
||||||
|
addEventListener("unload", function onUnload() {
|
||||||
|
removeEventListener("unload", onUnload);
|
||||||
|
Services.prefs.removeObserver(PREF, update);
|
||||||
|
});
|
||||||
|
|
||||||
|
return getNewTabPageURL();
|
||||||
});
|
});
|
||||||
|
|
||||||
var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
|
var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
|
||||||
|
|||||||
@@ -98,6 +98,12 @@ source-package::
|
|||||||
upload::
|
upload::
|
||||||
@$(MAKE) -C browser/installer upload
|
@$(MAKE) -C browser/installer upload
|
||||||
|
|
||||||
|
source-upload::
|
||||||
|
@$(MAKE) -C browser/installer source-upload
|
||||||
|
|
||||||
|
hg-bundle::
|
||||||
|
@$(MAKE) -C browser/installer hg-bundle
|
||||||
|
|
||||||
l10n-check::
|
l10n-check::
|
||||||
@$(MAKE) -C browser/locales l10n-check
|
@$(MAKE) -C browser/locales l10n-check
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() {
|
|||||||
XPCOMUtils.defineLazyModuleGetter(this, "KeywordURLResetPrompter",
|
XPCOMUtils.defineLazyModuleGetter(this, "KeywordURLResetPrompter",
|
||||||
"resource:///modules/KeywordURLResetPrompter.jsm");
|
"resource:///modules/KeywordURLResetPrompter.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "webappsUI",
|
||||||
|
"resource://gre/modules/webappsUI.jsm");
|
||||||
|
|
||||||
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
||||||
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
|
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
|
||||||
|
|
||||||
@@ -346,6 +349,7 @@ BrowserGlue.prototype = {
|
|||||||
if (this._isPlacesShutdownObserver)
|
if (this._isPlacesShutdownObserver)
|
||||||
os.removeObserver(this, "places-shutdown");
|
os.removeObserver(this, "places-shutdown");
|
||||||
os.removeObserver(this, "defaultURIFixup-using-keyword-pref");
|
os.removeObserver(this, "defaultURIFixup-using-keyword-pref");
|
||||||
|
webappsUI.uninit();
|
||||||
},
|
},
|
||||||
|
|
||||||
_onAppDefaults: function BG__onAppDefaults() {
|
_onAppDefaults: function BG__onAppDefaults() {
|
||||||
@@ -370,6 +374,9 @@ BrowserGlue.prototype = {
|
|||||||
// handle any UI migration
|
// handle any UI migration
|
||||||
this._migrateUI();
|
this._migrateUI();
|
||||||
|
|
||||||
|
// Initialize webapps UI
|
||||||
|
webappsUI.init();
|
||||||
|
|
||||||
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
|
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -405,7 +412,6 @@ BrowserGlue.prototype = {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Show update notification, if needed.
|
// Show update notification, if needed.
|
||||||
if (Services.prefs.prefHasUserValue("app.update.postupdate"))
|
if (Services.prefs.prefHasUserValue("app.update.postupdate"))
|
||||||
this._showUpdateNotification();
|
this._showUpdateNotification();
|
||||||
|
|||||||
@@ -376,31 +376,26 @@ PlacesViewBase.prototype = {
|
|||||||
_setLivemarkStatusMenuItem:
|
_setLivemarkStatusMenuItem:
|
||||||
function PVB_setLivemarkStatusMenuItem(aPopup, aStatus) {
|
function PVB_setLivemarkStatusMenuItem(aPopup, aStatus) {
|
||||||
let statusMenuitem = aPopup._statusMenuitem;
|
let statusMenuitem = aPopup._statusMenuitem;
|
||||||
let stringId = "";
|
if (!statusMenuitem) {
|
||||||
if (aStatus == Ci.mozILivemark.STATUS_LOADING)
|
|
||||||
stringId = "bookmarksLivemarkLoading";
|
|
||||||
else if (aStatus == Ci.mozILivemark.STATUS_FAILED)
|
|
||||||
stringId = "bookmarksLivemarkFailed";
|
|
||||||
|
|
||||||
if (stringId && !statusMenuitem) {
|
|
||||||
// Create the status menuitem and cache it in the popup object.
|
// Create the status menuitem and cache it in the popup object.
|
||||||
statusMenuitem = document.createElement("menuitem");
|
statusMenuitem = document.createElement("menuitem");
|
||||||
statusMenuitem.setAttribute("livemarkStatus", stringId);
|
|
||||||
statusMenuitem.className = "livemarkstatus-menuitem";
|
statusMenuitem.className = "livemarkstatus-menuitem";
|
||||||
statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
|
|
||||||
statusMenuitem.setAttribute("disabled", true);
|
statusMenuitem.setAttribute("disabled", true);
|
||||||
aPopup.insertBefore(statusMenuitem, aPopup._startMarker.nextSibling);
|
|
||||||
aPopup._statusMenuitem = statusMenuitem;
|
aPopup._statusMenuitem = statusMenuitem;
|
||||||
}
|
}
|
||||||
else if (stringId &&
|
|
||||||
statusMenuitem.getAttribute("livemarkStatus") != stringId) {
|
if (aStatus == Ci.mozILivemark.STATUS_LOADING ||
|
||||||
|
aStatus == Ci.mozILivemark.STATUS_FAILED) {
|
||||||
// Status has changed, update the cached status menuitem.
|
// Status has changed, update the cached status menuitem.
|
||||||
|
let stringId = aStatus == Ci.mozILivemark.STATUS_LOADING ?
|
||||||
|
"bookmarksLivemarkLoading" : "bookmarksLivemarkFailed";
|
||||||
statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
|
statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
|
||||||
|
if (aPopup._startMarker.nextSibling != statusMenuitem)
|
||||||
|
aPopup.insertBefore(statusMenuitem, aPopup._startMarker.nextSibling);
|
||||||
}
|
}
|
||||||
else if (!stringId && statusMenuitem) {
|
else {
|
||||||
// The livemark has finished loading.
|
// The livemark has finished loading.
|
||||||
aPopup.removeChild(aPopup._statusMenuitem);
|
aPopup.removeChild(aPopup._statusMenuitem);
|
||||||
aPopup._statusMenuitem = null;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -892,6 +887,14 @@ function PlacesToolbar(aPlace) {
|
|||||||
this._addEventListeners(this._rootElt, ["overflow", "underflow"], true);
|
this._addEventListeners(this._rootElt, ["overflow", "underflow"], true);
|
||||||
this._addEventListeners(window, ["resize", "unload"], false);
|
this._addEventListeners(window, ["resize", "unload"], false);
|
||||||
|
|
||||||
|
// If personal-bookmarks has been dragged to the tabs toolbar,
|
||||||
|
// we have to track addition and removals of tabs, to properly
|
||||||
|
// recalculate the available space for bookmarks.
|
||||||
|
// TODO (bug 734730): Use a performant mutation listener when available.
|
||||||
|
if (this._viewElt.parentNode.parentNode == document.getElementById("TabsToolbar")) {
|
||||||
|
this._addEventListeners(gBrowser.tabContainer, ["TabOpen", "TabClose"], false);
|
||||||
|
}
|
||||||
|
|
||||||
PlacesViewBase.call(this, aPlace);
|
PlacesViewBase.call(this, aPlace);
|
||||||
|
|
||||||
Services.telemetry.getHistogramById("FX_BOOKMARKS_TOOLBAR_INIT_MS")
|
Services.telemetry.getHistogramById("FX_BOOKMARKS_TOOLBAR_INIT_MS")
|
||||||
@@ -918,6 +921,7 @@ PlacesToolbar.prototype = {
|
|||||||
true);
|
true);
|
||||||
this._removeEventListeners(this._rootElt, ["overflow", "underflow"], true);
|
this._removeEventListeners(this._rootElt, ["overflow", "underflow"], true);
|
||||||
this._removeEventListeners(window, ["resize", "unload"], false);
|
this._removeEventListeners(window, ["resize", "unload"], false);
|
||||||
|
this._removeEventListeners(gBrowser.tabContainer, ["TabOpen", "TabClose"], false);
|
||||||
|
|
||||||
PlacesViewBase.prototype.uninit.apply(this, arguments);
|
PlacesViewBase.prototype.uninit.apply(this, arguments);
|
||||||
},
|
},
|
||||||
@@ -1017,9 +1021,10 @@ PlacesToolbar.prototype = {
|
|||||||
|
|
||||||
_updateChevronPopupNodesVisibility:
|
_updateChevronPopupNodesVisibility:
|
||||||
function PT__updateChevronPopupNodesVisibility() {
|
function PT__updateChevronPopupNodesVisibility() {
|
||||||
for (let i = 0; i < this._chevronPopup.childNodes.length; i++) {
|
for (let i = 0, node = this._chevronPopup._startMarker.nextSibling;
|
||||||
this._chevronPopup.childNodes[i].hidden =
|
node != this._chevronPopup._endMarker;
|
||||||
this._rootElt.childNodes[i].style.visibility != "hidden";
|
i++, node = node.nextSibling) {
|
||||||
|
node.hidden = this._rootElt.childNodes[i].style.visibility != "hidden";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1071,7 +1076,11 @@ PlacesToolbar.prototype = {
|
|||||||
if (aEvent.detail == 0)
|
if (aEvent.detail == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
this.updateChevron();
|
||||||
this._chevron.collapsed = true;
|
this._chevron.collapsed = true;
|
||||||
|
break;
|
||||||
|
case "TabOpen":
|
||||||
|
case "TabClose":
|
||||||
this.updateChevron();
|
this.updateChevron();
|
||||||
break;
|
break;
|
||||||
case "dragstart":
|
case "dragstart":
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
|||||||
* Hint: This is the default value because the 'New Tab Page' is the only
|
* Hint: This is the default value because the 'New Tab Page' is the only
|
||||||
* client for now.
|
* client for now.
|
||||||
*/
|
*/
|
||||||
const THUMBNAIL_WIDTH = 201;
|
const THUMBNAIL_WIDTH = 400;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default height for page thumbnails.
|
* The default height for page thumbnails.
|
||||||
@@ -26,7 +26,7 @@ const THUMBNAIL_WIDTH = 201;
|
|||||||
* Hint: This is the default value because the 'New Tab Page' is the only
|
* Hint: This is the default value because the 'New Tab Page' is the only
|
||||||
* client for now.
|
* client for now.
|
||||||
*/
|
*/
|
||||||
const THUMBNAIL_HEIGHT = 127;
|
const THUMBNAIL_HEIGHT = 225;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default background color for page thumbnails.
|
* The default background color for page thumbnails.
|
||||||
|
|||||||
@@ -18,3 +18,6 @@ ac_add_options --with-ccache=/usr/bin/ccache
|
|||||||
|
|
||||||
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||||
ac_add_options --enable-warnings-as-errors
|
ac_add_options --enable-warnings-as-errors
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -27,3 +27,6 @@ ac_add_options --with-ccache=/usr/bin/ccache
|
|||||||
|
|
||||||
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||||
ac_add_options --enable-warnings-as-errors
|
ac_add_options --enable-warnings-as-errors
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -21,3 +21,6 @@ ac_add_options --enable-warnings-as-errors
|
|||||||
|
|
||||||
# Enable parallel compiling
|
# Enable parallel compiling
|
||||||
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -15,3 +15,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
|
|||||||
|
|
||||||
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||||
ac_add_options --enable-warnings-as-errors
|
ac_add_options --enable-warnings-as-errors
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -27,3 +27,6 @@ ac_add_options --with-ccache=/usr/bin/ccache
|
|||||||
|
|
||||||
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||||
ac_add_options --enable-warnings-as-errors
|
ac_add_options --enable-warnings-as-errors
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -21,3 +21,6 @@ ac_add_options --enable-warnings-as-errors
|
|||||||
|
|
||||||
# Enable parallel compiling
|
# Enable parallel compiling
|
||||||
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -22,3 +22,6 @@ ac_add_options --with-macbundlename-prefix=Firefox
|
|||||||
|
|
||||||
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||||
ac_add_options --enable-warnings-as-errors
|
ac_add_options --enable-warnings-as-errors
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -17,3 +17,6 @@ ac_add_options --enable-warnings-as-errors
|
|||||||
|
|
||||||
# Enable parallel compiling
|
# Enable parallel compiling
|
||||||
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -10,3 +10,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
|
|||||||
export MOZILLA_OFFICIAL=1
|
export MOZILLA_OFFICIAL=1
|
||||||
|
|
||||||
ac_add_options --with-macbundlename-prefix=Firefox
|
ac_add_options --with-macbundlename-prefix=Firefox
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -15,3 +15,6 @@ ac_add_options --with-macbundlename-prefix=Firefox
|
|||||||
|
|
||||||
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||||
ac_add_options --enable-warnings-as-errors
|
ac_add_options --enable-warnings-as-errors
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -8,3 +8,6 @@ export MOZILLA_OFFICIAL=1
|
|||||||
mk_add_options MOZ_MAKE_FLAGS=-j1
|
mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||||
|
|
||||||
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
|
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -17,3 +17,6 @@ export MOZ_TELEMETRY_REPORTING=1
|
|||||||
mk_add_options MOZ_MAKE_FLAGS=-j1
|
mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||||
|
|
||||||
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
|
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -13,3 +13,6 @@ export MOZILLA_OFFICIAL=1
|
|||||||
export MOZ_TELEMETRY_REPORTING=1
|
export MOZ_TELEMETRY_REPORTING=1
|
||||||
|
|
||||||
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
|
. $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|||||||
@@ -9,3 +9,8 @@ ac_add_options --enable-signmar
|
|||||||
export MOZILLA_OFFICIAL=1
|
export MOZILLA_OFFICIAL=1
|
||||||
|
|
||||||
mk_add_options MOZ_MAKE_FLAGS=-j1
|
mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|
||||||
|
. $topsrcdir/browser/config/mozconfigs/win64/vs2010-mozconfig
|
||||||
|
|||||||
@@ -18,3 +18,8 @@ export MOZILLA_OFFICIAL=1
|
|||||||
export MOZ_TELEMETRY_REPORTING=1
|
export MOZ_TELEMETRY_REPORTING=1
|
||||||
|
|
||||||
mk_add_options MOZ_MAKE_FLAGS=-j1
|
mk_add_options MOZ_MAKE_FLAGS=-j1
|
||||||
|
|
||||||
|
# Package js shell.
|
||||||
|
export MOZ_PACKAGE_JSSHELL=1
|
||||||
|
|
||||||
|
. $topsrcdir/browser/config/mozconfigs/win64/vs2010-mozconfig
|
||||||
|
|||||||
16
browser/config/mozconfigs/win64/vs2010-mozconfig
Normal file
16
browser/config/mozconfigs/win64/vs2010-mozconfig
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
export INCLUDE=/c/tools/msvs10/vc/include:/c/tools/msvs10/vc/atlmfc/include:/c/tools/sdks/v7.0/include:/c/tools/sdks/v7.0/include/atl:/c/tools/sdks/dx10/include
|
||||||
|
export LIBPATH=/c/tools/msvs10/vc/lib/amd64:/c/tools/msvs10/vc/atlmfc/lib/amd64
|
||||||
|
export LIB=/c/tools/msvs10/vc/lib/amd64:/c/tools/msvs10/vc/atlmfc/lib/amd64:/c/tools/sdks/v7.0/lib/x64:/c/tools/sdks/dx10/lib/x64
|
||||||
|
export PATH="/c/tools/msvs10/Common7/IDE:/c/tools/msvs10/VC/BIN/amd64:/c/tools/msvs10/VC/BIN/x86_amd64:/c/tools/msvs10/VC/BIN:/c/tools/msvs10/Common7/Tools:/c/tools/msvs10/VC/VCPackages:${PATH}"
|
||||||
|
export WIN32_REDIST_DIR=/c/tools/msvs10/VC/redist/x64/Microsoft.VC100.CRT
|
||||||
|
|
||||||
|
# Use 32bit linker for PGO crash bug.
|
||||||
|
# https://connect.microsoft.com/VisualStudio/feedback/details/686117/
|
||||||
|
export LD=/c/tools/msvs10/VC/BIN/x86_amd64/link.exe
|
||||||
|
|
||||||
|
|
||||||
|
mk_add_options "export LIB=$LIB"
|
||||||
|
mk_add_options "export LIBPATH=$LIBPATH"
|
||||||
|
mk_add_options "export PATH=$PATH"
|
||||||
|
mk_add_options "export INCLUDE=$INCLUDE"
|
||||||
|
mk_add_options "export WIN32_REDIST_DIR=$WIN32_REDIST_DIR"
|
||||||
@@ -71,10 +71,11 @@ _BROWSER_TEST_FILES = \
|
|||||||
browser_dbg_script-switching.js \
|
browser_dbg_script-switching.js \
|
||||||
browser_dbg_pause-resume.js \
|
browser_dbg_pause-resume.js \
|
||||||
browser_dbg_update-editor-mode.js \
|
browser_dbg_update-editor-mode.js \
|
||||||
browser_dbg_select-line.js \
|
$(warning browser_dbg_select-line.js temporarily disabled due to oranges, see bug 726609) \
|
||||||
browser_dbg_clean-exit.js \
|
browser_dbg_clean-exit.js \
|
||||||
browser_dbg_bug723069_editor-breakpoints.js \
|
browser_dbg_bug723069_editor-breakpoints.js \
|
||||||
browser_dbg_bug731394_editor-contextmenu.js \
|
browser_dbg_bug731394_editor-contextmenu.js \
|
||||||
|
browser_dbg_displayName.js \
|
||||||
head.js \
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
@@ -89,6 +90,7 @@ _BROWSER_TEST_PAGES = \
|
|||||||
browser_dbg_frame-parameters.html \
|
browser_dbg_frame-parameters.html \
|
||||||
browser_dbg_update-editor-mode.html \
|
browser_dbg_update-editor-mode.html \
|
||||||
test-editor-mode \
|
test-editor-mode \
|
||||||
|
browser_dbg_displayName.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libs:: $(_BROWSER_TEST_FILES)
|
libs:: $(_BROWSER_TEST_FILES)
|
||||||
|
|||||||
26
browser/devtools/debugger/test/browser_dbg_displayName.html
Normal file
26
browser/devtools/debugger/test/browser_dbg_displayName.html
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head><title>Browser Debugger Test Tab</title>
|
||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var a = function() {
|
||||||
|
return function() {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var anon = a();
|
||||||
|
anon.displayName = "anonFunc";
|
||||||
|
|
||||||
|
function evalCall() {
|
||||||
|
eval("anon();");
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body></body>
|
||||||
|
|
||||||
|
</html>
|
||||||
53
browser/devtools/debugger/test/browser_dbg_displayName.js
Normal file
53
browser/devtools/debugger/test/browser_dbg_displayName.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gPane = null;
|
||||||
|
var gTab = null;
|
||||||
|
var gDebuggee = null;
|
||||||
|
var gDebugger = null;
|
||||||
|
|
||||||
|
const TAB_URL = EXAMPLE_URL + "browser_dbg_displayName.html";
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||||
|
gTab = aTab;
|
||||||
|
gDebuggee = aDebuggee;
|
||||||
|
gPane = aPane;
|
||||||
|
gDebugger = gPane.debuggerWindow;
|
||||||
|
|
||||||
|
testAnonCall();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testAnonCall() {
|
||||||
|
gPane.activeThread.addOneTimeListener("framesadded", function() {
|
||||||
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
|
||||||
|
let frames = gDebugger.DebuggerView.Stackframes._frames;
|
||||||
|
|
||||||
|
is(gDebugger.StackFrames.activeThread.state, "paused",
|
||||||
|
"Should only be getting stack frames while paused.");
|
||||||
|
|
||||||
|
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
|
||||||
|
"Should have three frames.");
|
||||||
|
|
||||||
|
is(frames.querySelector("#stackframe-0 .dbg-stackframe-name").textContent,
|
||||||
|
"anonFunc", "Frame name should be anonFunc");
|
||||||
|
|
||||||
|
resumeAndFinish();
|
||||||
|
}}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
gDebuggee.evalCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resumeAndFinish() {
|
||||||
|
gDebugger.StackFrames.activeThread.resume(function() {
|
||||||
|
removeTab(gTab);
|
||||||
|
gPane = null;
|
||||||
|
gDebuggee = null;
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -309,7 +309,7 @@ TreePanel.prototype = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle double-click events in the html tree panel.
|
* Handle double-click events in the html tree panel.
|
||||||
* (double-clicking an attribute value allows it to be edited)
|
* Double-clicking an attribute name or value allows it to be edited.
|
||||||
* @param aEvent
|
* @param aEvent
|
||||||
* The mouse event.
|
* The mouse event.
|
||||||
*/
|
*/
|
||||||
@@ -322,19 +322,33 @@ TreePanel.prototype = {
|
|||||||
|
|
||||||
let target = aEvent.target;
|
let target = aEvent.target;
|
||||||
|
|
||||||
|
if (!this.hasClass(target, "editable")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let repObj = this.getRepObject(target);
|
||||||
|
|
||||||
if (this.hasClass(target, "nodeValue")) {
|
if (this.hasClass(target, "nodeValue")) {
|
||||||
let repObj = this.getRepObject(target);
|
|
||||||
let attrName = target.getAttribute("data-attributeName");
|
let attrName = target.getAttribute("data-attributeName");
|
||||||
let attrVal = target.innerHTML;
|
let attrVal = target.innerHTML;
|
||||||
|
|
||||||
this.editAttributeValue(target, repObj, attrName, attrVal);
|
this.editAttribute(target, repObj, attrName, attrVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.hasClass(target, "nodeName")) {
|
||||||
|
let attrName = target.innerHTML;
|
||||||
|
let attrValNode = target.nextSibling.nextSibling; // skip 2 (=)
|
||||||
|
|
||||||
|
if (attrValNode)
|
||||||
|
this.editAttribute(target, repObj, attrName, attrValNode.innerHTML);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the editor for an attribute value.
|
* Starts the editor for an attribute name or value.
|
||||||
* @param aAttrObj
|
* @param aAttrObj
|
||||||
* The DOM object representing the attribute value in the HTML Tree
|
* The DOM object representing the attribute name or value in the HTML
|
||||||
|
* Tree.
|
||||||
* @param aRepObj
|
* @param aRepObj
|
||||||
* The original DOM (target) object being inspected/edited
|
* The original DOM (target) object being inspected/edited
|
||||||
* @param aAttrName
|
* @param aAttrName
|
||||||
@@ -342,8 +356,8 @@ TreePanel.prototype = {
|
|||||||
* @param aAttrVal
|
* @param aAttrVal
|
||||||
* The current value of the attribute being edited
|
* The current value of the attribute being edited
|
||||||
*/
|
*/
|
||||||
editAttributeValue:
|
editAttribute:
|
||||||
function TP_editAttributeValue(aAttrObj, aRepObj, aAttrName, aAttrVal)
|
function TP_editAttribute(aAttrObj, aRepObj, aAttrName, aAttrVal)
|
||||||
{
|
{
|
||||||
let editor = this.treeBrowserDocument.getElementById("attribute-editor");
|
let editor = this.treeBrowserDocument.getElementById("attribute-editor");
|
||||||
let editorInput =
|
let editorInput =
|
||||||
@@ -357,7 +371,8 @@ TreePanel.prototype = {
|
|||||||
this.editingContext = {
|
this.editingContext = {
|
||||||
attrObj: aAttrObj,
|
attrObj: aAttrObj,
|
||||||
repObj: aRepObj,
|
repObj: aRepObj,
|
||||||
attrName: aAttrName
|
attrName: aAttrName,
|
||||||
|
attrValue: aAttrVal
|
||||||
};
|
};
|
||||||
|
|
||||||
// highlight attribute-value node in tree while editing
|
// highlight attribute-value node in tree while editing
|
||||||
@@ -367,7 +382,7 @@ TreePanel.prototype = {
|
|||||||
this.addClass(editor, "editing");
|
this.addClass(editor, "editing");
|
||||||
|
|
||||||
// offset the editor below the attribute-value node being edited
|
// offset the editor below the attribute-value node being edited
|
||||||
let editorVeritcalOffset = 2;
|
let editorVerticalOffset = 2;
|
||||||
|
|
||||||
// keep the editor comfortably within the bounds of the viewport
|
// keep the editor comfortably within the bounds of the viewport
|
||||||
let editorViewportBoundary = 5;
|
let editorViewportBoundary = 5;
|
||||||
@@ -384,7 +399,7 @@ TreePanel.prototype = {
|
|||||||
// center the editor against the attribute value
|
// center the editor against the attribute value
|
||||||
((editorDims.width - attrDims.width) / 2);
|
((editorDims.width - attrDims.width) / 2);
|
||||||
let editorTop = attrDims.top + this.treeIFrame.contentWindow.scrollY +
|
let editorTop = attrDims.top + this.treeIFrame.contentWindow.scrollY +
|
||||||
attrDims.height + editorVeritcalOffset;
|
attrDims.height + editorVerticalOffset;
|
||||||
|
|
||||||
// but, make sure the editor stays within the visible viewport
|
// but, make sure the editor stays within the visible viewport
|
||||||
editorLeft = Math.max(0, Math.min(
|
editorLeft = Math.max(0, Math.min(
|
||||||
@@ -403,8 +418,13 @@ TreePanel.prototype = {
|
|||||||
editor.style.top = editorTop + "px";
|
editor.style.top = editorTop + "px";
|
||||||
|
|
||||||
// set and select the text
|
// set and select the text
|
||||||
editorInput.value = aAttrVal;
|
if (this.hasClass(aAttrObj, "nodeValue")) {
|
||||||
editorInput.select();
|
editorInput.value = aAttrVal;
|
||||||
|
editorInput.select();
|
||||||
|
} else {
|
||||||
|
editorInput.value = aAttrName;
|
||||||
|
editorInput.select();
|
||||||
|
}
|
||||||
|
|
||||||
// listen for editor specific events
|
// listen for editor specific events
|
||||||
this.bindEditorEvent(editor, "click", function(aEvent) {
|
this.bindEditorEvent(editor, "click", function(aEvent) {
|
||||||
@@ -510,15 +530,32 @@ TreePanel.prototype = {
|
|||||||
{
|
{
|
||||||
let editorInput =
|
let editorInput =
|
||||||
this.treeBrowserDocument.getElementById("attribute-editor-input");
|
this.treeBrowserDocument.getElementById("attribute-editor-input");
|
||||||
|
let dirty = false;
|
||||||
|
|
||||||
// set the new attribute value on the original target DOM element
|
if (this.hasClass(this.editingContext.attrObj, "nodeValue")) {
|
||||||
this.editingContext.repObj.setAttribute(this.editingContext.attrName,
|
// set the new attribute value on the original target DOM element
|
||||||
editorInput.value);
|
this.editingContext.repObj.setAttribute(this.editingContext.attrName,
|
||||||
|
editorInput.value);
|
||||||
|
|
||||||
// update the HTML tree attribute value
|
// update the HTML tree attribute value
|
||||||
this.editingContext.attrObj.innerHTML = editorInput.value;
|
this.editingContext.attrObj.innerHTML = editorInput.value;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
this.IUI.isDirty = true;
|
if (this.hasClass(this.editingContext.attrObj, "nodeName")) {
|
||||||
|
// remove the original attribute from the original target DOM element
|
||||||
|
this.editingContext.repObj.removeAttribute(this.editingContext.attrName);
|
||||||
|
|
||||||
|
// set the new attribute value on the original target DOM element
|
||||||
|
this.editingContext.repObj.setAttribute(editorInput.value,
|
||||||
|
this.editingContext.attrValue);
|
||||||
|
|
||||||
|
// update the HTML tree attribute value
|
||||||
|
this.editingContext.attrObj.innerHTML = editorInput.value;
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.IUI.isDirty = dirty;
|
||||||
this.IUI.nodeChanged(this.registrationObject);
|
this.IUI.nodeChanged(this.registrationObject);
|
||||||
|
|
||||||
// event notification
|
// event notification
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
* Paul Rouget <paul@mozilla.com>
|
* Paul Rouget <paul@mozilla.com>
|
||||||
* Kyle Simpson <ksimpson@mozilla.com>
|
* Kyle Simpson <ksimpson@mozilla.com>
|
||||||
* Johan Charlez <johan.charlez@gmail.com>
|
* Johan Charlez <johan.charlez@gmail.com>
|
||||||
|
* Mike Ratcliffe <mratcliffe@mozilla.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
@@ -104,6 +105,15 @@ function InspectorUI(aWindow)
|
|||||||
this.toolEvents = {};
|
this.toolEvents = {};
|
||||||
this.store = new InspectorStore();
|
this.store = new InspectorStore();
|
||||||
this.INSPECTOR_NOTIFICATIONS = INSPECTOR_NOTIFICATIONS;
|
this.INSPECTOR_NOTIFICATIONS = INSPECTOR_NOTIFICATIONS;
|
||||||
|
|
||||||
|
// Set the tooltip of the inspect button.
|
||||||
|
let keysbundle = Services.strings.createBundle(
|
||||||
|
"chrome://global/locale/keys.properties");
|
||||||
|
let returnString = keysbundle.GetStringFromName("VK_RETURN");
|
||||||
|
let tooltip = this.strings.formatStringFromName("inspectButton.tooltiptext",
|
||||||
|
[returnString], 1);
|
||||||
|
let button = this.chromeDoc.getElementById("inspector-inspect-toolbutton");
|
||||||
|
button.setAttribute("tooltiptext", tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
InspectorUI.prototype = {
|
InspectorUI.prototype = {
|
||||||
@@ -845,9 +855,7 @@ InspectorUI.prototype = {
|
|||||||
*/
|
*/
|
||||||
copyInnerHTML: function IUI_copyInnerHTML()
|
copyInnerHTML: function IUI_copyInnerHTML()
|
||||||
{
|
{
|
||||||
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
|
clipboardHelper.copyString(this.selection.innerHTML);
|
||||||
getService(Ci.nsIClipboardHelper);
|
|
||||||
clipboard.copyString(this.selection.innerHTML);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -856,9 +864,7 @@ InspectorUI.prototype = {
|
|||||||
*/
|
*/
|
||||||
copyOuterHTML: function IUI_copyOuterHTML()
|
copyOuterHTML: function IUI_copyOuterHTML()
|
||||||
{
|
{
|
||||||
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
|
clipboardHelper.copyString(this.selection.outerHTML);
|
||||||
getService(Ci.nsIClipboardHelper);
|
|
||||||
clipboard.copyString(this.selection.outerHTML);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -926,12 +932,34 @@ InspectorUI.prototype = {
|
|||||||
|
|
||||||
this.ruleView = new CssRuleView(doc, ruleViewStore);
|
this.ruleView = new CssRuleView(doc, ruleViewStore);
|
||||||
|
|
||||||
|
// Add event handlers bound to this.
|
||||||
this.boundRuleViewChanged = this.ruleViewChanged.bind(this);
|
this.boundRuleViewChanged = this.ruleViewChanged.bind(this);
|
||||||
this.ruleView.element.addEventListener("CssRuleViewChanged",
|
this.ruleView.element.addEventListener("CssRuleViewChanged",
|
||||||
this.boundRuleViewChanged);
|
this.boundRuleViewChanged);
|
||||||
this.cssRuleViewBoundCSSLinkClicked = this.ruleViewCSSLinkClicked.bind(this);
|
this.cssRuleViewBoundCSSLinkClicked = this.ruleViewCSSLinkClicked.bind(this);
|
||||||
this.ruleView.element.addEventListener("CssRuleViewCSSLinkClicked",
|
this.ruleView.element.addEventListener("CssRuleViewCSSLinkClicked",
|
||||||
this.cssRuleViewBoundCSSLinkClicked);
|
this.cssRuleViewBoundCSSLinkClicked);
|
||||||
|
this.cssRuleViewBoundMouseDown = this.ruleViewMouseDown.bind(this);
|
||||||
|
this.ruleView.element.addEventListener("mousedown",
|
||||||
|
this.cssRuleViewBoundMouseDown);
|
||||||
|
this.cssRuleViewBoundMouseUp = this.ruleViewMouseUp.bind(this);
|
||||||
|
this.ruleView.element.addEventListener("mouseup",
|
||||||
|
this.cssRuleViewBoundMouseUp);
|
||||||
|
this.cssRuleViewBoundMouseMove = this.ruleViewMouseMove.bind(this);
|
||||||
|
this.cssRuleViewBoundMenuUpdate = this.ruleViewMenuUpdate.bind(this);
|
||||||
|
|
||||||
|
this.cssRuleViewBoundCopy = this.ruleViewCopy.bind(this);
|
||||||
|
iframe.addEventListener("copy", this.cssRuleViewBoundCopy);
|
||||||
|
|
||||||
|
this.cssRuleViewBoundCopyRule = this.ruleViewCopyRule.bind(this);
|
||||||
|
this.cssRuleViewBoundCopyDeclaration =
|
||||||
|
this.ruleViewCopyDeclaration.bind(this);
|
||||||
|
this.cssRuleViewBoundCopyProperty = this.ruleViewCopyProperty.bind(this);
|
||||||
|
this.cssRuleViewBoundCopyPropertyValue =
|
||||||
|
this.ruleViewCopyPropertyValue.bind(this);
|
||||||
|
|
||||||
|
// Add the rule view's context menu.
|
||||||
|
this.ruleViewAddContextMenu();
|
||||||
|
|
||||||
doc.documentElement.appendChild(this.ruleView.element);
|
doc.documentElement.appendChild(this.ruleView.element);
|
||||||
this.ruleView.highlight(this.selection);
|
this.ruleView.highlight(this.selection);
|
||||||
@@ -1002,19 +1030,356 @@ InspectorUI.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the mousedown handler for the rule view. We use it to track whether
|
||||||
|
* text is currently getting selected.
|
||||||
|
* .
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
ruleViewMouseDown: function IUI_ruleViewMouseDown(aEvent)
|
||||||
|
{
|
||||||
|
this.ruleView.element.addEventListener("mousemove",
|
||||||
|
this.cssRuleViewBoundMouseMove);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the mouseup handler for the rule view. We use it to track whether
|
||||||
|
* text is currently getting selected.
|
||||||
|
* .
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
ruleViewMouseUp: function IUI_ruleViewMouseUp(aEvent)
|
||||||
|
{
|
||||||
|
this.ruleView.element.removeEventListener("mousemove",
|
||||||
|
this.cssRuleViewBoundMouseMove);
|
||||||
|
this.ruleView._selectionMode = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the mousemove handler for the rule view. We use it to track whether
|
||||||
|
* text is currently getting selected.
|
||||||
|
* .
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
ruleViewMouseMove: function IUI_ruleViewMouseMove(aEvent)
|
||||||
|
{
|
||||||
|
this.ruleView._selectionMode = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a context menu to the rule view.
|
||||||
|
*/
|
||||||
|
ruleViewAddContextMenu: function IUI_ruleViewAddContextMenu()
|
||||||
|
{
|
||||||
|
let iframe = this.getToolIframe(this.ruleViewObject);
|
||||||
|
let popupSet = this.chromeDoc.getElementById("mainPopupSet");
|
||||||
|
let menu = this.chromeDoc.createElement("menupopup");
|
||||||
|
menu.addEventListener("popupshowing", this.cssRuleViewBoundMenuUpdate);
|
||||||
|
menu.id = "rule-view-context-menu";
|
||||||
|
|
||||||
|
// Copy selection
|
||||||
|
let label = styleInspectorStrings
|
||||||
|
.GetStringFromName("rule.contextmenu.copyselection");
|
||||||
|
let accessKey = styleInspectorStrings
|
||||||
|
.GetStringFromName("rule.contextmenu.copyselection.accesskey");
|
||||||
|
let item = this.chromeDoc.createElement("menuitem");
|
||||||
|
item.id = "rule-view-copy";
|
||||||
|
item.setAttribute("label", label);
|
||||||
|
item.setAttribute("accesskey", accessKey);
|
||||||
|
item.addEventListener("command", this.cssRuleViewBoundCopy);
|
||||||
|
menu.appendChild(item);
|
||||||
|
|
||||||
|
// Copy rule
|
||||||
|
label = styleInspectorStrings.
|
||||||
|
GetStringFromName("rule.contextmenu.copyrule");
|
||||||
|
accessKey = styleInspectorStrings.
|
||||||
|
GetStringFromName("rule.contextmenu.copyrule.accesskey");
|
||||||
|
item = this.chromeDoc.createElement("menuitem");
|
||||||
|
item.id = "rule-view-copy-rule";
|
||||||
|
item.setAttribute("label", label);
|
||||||
|
item.setAttribute("accesskey", accessKey);
|
||||||
|
item.addEventListener("command", this.cssRuleViewBoundCopyRule);
|
||||||
|
menu.appendChild(item);
|
||||||
|
|
||||||
|
// Copy declaration
|
||||||
|
label = styleInspectorStrings.
|
||||||
|
GetStringFromName("rule.contextmenu.copydeclaration");
|
||||||
|
accessKey = styleInspectorStrings.
|
||||||
|
GetStringFromName("rule.contextmenu.copydeclaration.accesskey");
|
||||||
|
item = this.chromeDoc.createElement("menuitem");
|
||||||
|
item.id = "rule-view-copy-declaration";
|
||||||
|
item.setAttribute("label", label);
|
||||||
|
item.setAttribute("accesskey", accessKey);
|
||||||
|
item.addEventListener("command", this.cssRuleViewBoundCopyDeclaration);
|
||||||
|
menu.appendChild(item);
|
||||||
|
|
||||||
|
// Copy property name
|
||||||
|
label = styleInspectorStrings.
|
||||||
|
GetStringFromName("rule.contextmenu.copyproperty");
|
||||||
|
accessKey = styleInspectorStrings.
|
||||||
|
GetStringFromName("rule.contextmenu.copyproperty.accesskey");
|
||||||
|
item = this.chromeDoc.createElement("menuitem");
|
||||||
|
item.id = "rule-view-copy-property";
|
||||||
|
item.setAttribute("label", label);
|
||||||
|
item.setAttribute("accesskey", accessKey);
|
||||||
|
item.addEventListener("command", this.cssRuleViewBoundCopyProperty);
|
||||||
|
menu.appendChild(item);
|
||||||
|
|
||||||
|
// Copy property value
|
||||||
|
label = styleInspectorStrings.
|
||||||
|
GetStringFromName("rule.contextmenu.copypropertyvalue");
|
||||||
|
accessKey = styleInspectorStrings.
|
||||||
|
GetStringFromName("rule.contextmenu.copypropertyvalue.accesskey");
|
||||||
|
item = this.chromeDoc.createElement("menuitem");
|
||||||
|
item.id = "rule-view-copy-property-value";
|
||||||
|
item.setAttribute("label", label);
|
||||||
|
item.setAttribute("accesskey", accessKey);
|
||||||
|
item.addEventListener("command", this.cssRuleViewBoundCopyPropertyValue);
|
||||||
|
menu.appendChild(item);
|
||||||
|
|
||||||
|
popupSet.appendChild(menu);
|
||||||
|
|
||||||
|
iframe.setAttribute("context", menu.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the rule view's context menu by disabling irrelevant menuitems and
|
||||||
|
* enabling relevant ones.
|
||||||
|
*
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
ruleViewMenuUpdate: function IUI_ruleViewMenuUpdate(aEvent)
|
||||||
|
{
|
||||||
|
let iframe = this.getToolIframe(this.ruleViewObject);
|
||||||
|
let win = iframe.contentWindow;
|
||||||
|
|
||||||
|
// Copy selection.
|
||||||
|
let disable = win.getSelection().isCollapsed;
|
||||||
|
let menuitem = this.chromeDoc.getElementById("rule-view-copy");
|
||||||
|
menuitem.disabled = disable;
|
||||||
|
|
||||||
|
// Copy property, copy property name & copy property value.
|
||||||
|
let node = this.chromeDoc.popupNode;
|
||||||
|
if (!node.classList.contains("ruleview-property") &&
|
||||||
|
!node.classList.contains("ruleview-computed")) {
|
||||||
|
while (node = node.parentElement) {
|
||||||
|
if (node.classList.contains("ruleview-property") ||
|
||||||
|
node.classList.contains("ruleview-computed")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let disablePropertyItems = !node || (node &&
|
||||||
|
!node.classList.contains("ruleview-property") &&
|
||||||
|
!node.classList.contains("ruleview-computed"));
|
||||||
|
|
||||||
|
menuitem = this.chromeDoc.querySelector("#rule-view-copy-declaration");
|
||||||
|
menuitem.disabled = disablePropertyItems;
|
||||||
|
menuitem = this.chromeDoc.querySelector("#rule-view-copy-property");
|
||||||
|
menuitem.disabled = disablePropertyItems;
|
||||||
|
menuitem = this.chromeDoc.querySelector("#rule-view-copy-property-value");
|
||||||
|
menuitem.disabled = disablePropertyItems;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy selected text from the rule view.
|
||||||
|
*
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
ruleViewCopy: function IUI_ruleViewCopy(aEvent)
|
||||||
|
{
|
||||||
|
let iframe = this.getToolIframe(this.ruleViewObject);
|
||||||
|
let win = iframe.contentWindow;
|
||||||
|
let text = win.getSelection().toString();
|
||||||
|
|
||||||
|
// Remove any double newlines.
|
||||||
|
text = text.replace(/(\r?\n)\r?\n/g, "$1");
|
||||||
|
|
||||||
|
// Remove "inline"
|
||||||
|
let inline = styleInspectorStrings.GetStringFromName("rule.sourceInline");
|
||||||
|
let rx = new RegExp("^" + inline + "\\r?\\n?", "g");
|
||||||
|
text = text.replace(rx, "");
|
||||||
|
|
||||||
|
// Remove file:line
|
||||||
|
text = text.replace(/[\w\.]+:\d+(\r?\n)/g, "$1");
|
||||||
|
|
||||||
|
// Remove inherited from: line
|
||||||
|
let inheritedFrom = styleInspectorStrings
|
||||||
|
.GetStringFromName("rule.inheritedSource");
|
||||||
|
inheritedFrom = inheritedFrom.replace(/\s%S\s\(%S\)/g, "");
|
||||||
|
rx = new RegExp("(\r?\n)" + inheritedFrom + ".*", "g");
|
||||||
|
text = text.replace(rx, "$1");
|
||||||
|
|
||||||
|
clipboardHelper.copyString(text);
|
||||||
|
|
||||||
|
if (aEvent) {
|
||||||
|
aEvent.preventDefault();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a rule from the rule view.
|
||||||
|
*
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
ruleViewCopyRule: function IUI_ruleViewCopyRule(aEvent)
|
||||||
|
{
|
||||||
|
let node = this.chromeDoc.popupNode;
|
||||||
|
if (node.className != "ruleview-code") {
|
||||||
|
if (node.className == "ruleview-rule-source") {
|
||||||
|
node = node.nextElementSibling;
|
||||||
|
} else {
|
||||||
|
while (node = node.parentElement) {
|
||||||
|
if (node.className == "ruleview-code") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.className == "ruleview-code") {
|
||||||
|
// We need to strip expanded properties from the node because we use
|
||||||
|
// node.textContent below, which also gets text from hidden nodes. The
|
||||||
|
// simplest way to do this is to clone the node and remove them from the
|
||||||
|
// clone.
|
||||||
|
node = node.cloneNode();
|
||||||
|
let computed = node.querySelector(".ruleview-computedlist");
|
||||||
|
if (computed) {
|
||||||
|
computed.parentNode.removeChild(computed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = node.textContent;
|
||||||
|
|
||||||
|
// Format the rule
|
||||||
|
if (osString == "WINNT") {
|
||||||
|
text = text.replace(/{/g, "{\r\n ");
|
||||||
|
text = text.replace(/;/g, ";\r\n ");
|
||||||
|
text = text.replace(/\s*}/g, "\r\n}");
|
||||||
|
} else {
|
||||||
|
text = text.replace(/{/g, "{\n ");
|
||||||
|
text = text.replace(/;/g, ";\n ");
|
||||||
|
text = text.replace(/\s*}/g, "\n}");
|
||||||
|
}
|
||||||
|
|
||||||
|
clipboardHelper.copyString(text);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a declaration from the rule view.
|
||||||
|
*
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
ruleViewCopyDeclaration: function IUI_ruleViewCopyDeclaration(aEvent)
|
||||||
|
{
|
||||||
|
let node = this.chromeDoc.popupNode;
|
||||||
|
if (!node.classList.contains("ruleview-property") &&
|
||||||
|
!node.classList.contains("ruleview-computed")) {
|
||||||
|
while (node = node.parentElement) {
|
||||||
|
if (node.classList.contains("ruleview-property") ||
|
||||||
|
node.classList.contains("ruleview-computed")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to strip expanded properties from the node because we use
|
||||||
|
// node.textContent below, which also gets text from hidden nodes. The
|
||||||
|
// simplest way to do this is to clone the node and remove them from the
|
||||||
|
// clone.
|
||||||
|
node = node.cloneNode();
|
||||||
|
let computed = node.querySelector(".ruleview-computedlist");
|
||||||
|
if (computed) {
|
||||||
|
computed.parentNode.removeChild(computed);
|
||||||
|
}
|
||||||
|
clipboardHelper.copyString(node.textContent);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a property name from the rule view.
|
||||||
|
*
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
ruleViewCopyProperty: function IUI_ruleViewCopyProperty(aEvent)
|
||||||
|
{
|
||||||
|
let node = this.chromeDoc.popupNode;
|
||||||
|
|
||||||
|
if (!node.classList.contains("ruleview-propertyname")) {
|
||||||
|
node = node.querySelector(".ruleview-propertyname");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
clipboardHelper.copyString(node.textContent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a property value from the rule view.
|
||||||
|
*
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
ruleViewCopyPropertyValue: function IUI_ruleViewCopyPropertyValue(aEvent)
|
||||||
|
{
|
||||||
|
let node = this.chromeDoc.popupNode;
|
||||||
|
|
||||||
|
if (!node.classList.contains("ruleview-propertyvalue")) {
|
||||||
|
node = node.querySelector(".ruleview-propertyvalue");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
clipboardHelper.copyString(node.textContent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the rule view.
|
* Destroy the rule view.
|
||||||
*/
|
*/
|
||||||
destroyRuleView: function IUI_destroyRuleView()
|
destroyRuleView: function IUI_destroyRuleView()
|
||||||
{
|
{
|
||||||
let iframe = this.getToolIframe(this.ruleViewObject);
|
let iframe = this.getToolIframe(this.ruleViewObject);
|
||||||
|
iframe.removeEventListener("copy", this.cssRuleViewBoundCopy);
|
||||||
iframe.parentNode.removeChild(iframe);
|
iframe.parentNode.removeChild(iframe);
|
||||||
|
|
||||||
if (this.ruleView) {
|
if (this.ruleView) {
|
||||||
|
let menu = this.chromeDoc.querySelector("#rule-view-context-menu");
|
||||||
|
if (menu) {
|
||||||
|
// Copy
|
||||||
|
let menuitem = this.chromeDoc.querySelector("#rule-view-copy");
|
||||||
|
menuitem.removeEventListener("command", this.cssRuleViewBoundCopy);
|
||||||
|
|
||||||
|
// Copy rule
|
||||||
|
menuitem = this.chromeDoc.querySelector("#rule-view-copy-rule");
|
||||||
|
menuitem.removeEventListener("command", this.cssRuleViewBoundCopyRule);
|
||||||
|
|
||||||
|
// Copy property
|
||||||
|
menuitem = this.chromeDoc.querySelector("#rule-view-copy-declaration");
|
||||||
|
menuitem.removeEventListener("command",
|
||||||
|
this.cssRuleViewBoundCopyDeclaration);
|
||||||
|
|
||||||
|
// Copy property name
|
||||||
|
menuitem = this.chromeDoc.querySelector("#rule-view-copy-property");
|
||||||
|
menuitem.removeEventListener("command",
|
||||||
|
this.cssRuleViewBoundCopyProperty);
|
||||||
|
|
||||||
|
// Copy property value
|
||||||
|
menuitem = this.chromeDoc.querySelector("#rule-view-copy-property-value");
|
||||||
|
menuitem.removeEventListener("command",
|
||||||
|
this.cssRuleViewBoundCopyPropertyValue);
|
||||||
|
|
||||||
|
menu.removeEventListener("popupshowing", this.cssRuleViewBoundMenuUpdate);
|
||||||
|
menu.parentNode.removeChild(menu);
|
||||||
|
}
|
||||||
|
|
||||||
this.ruleView.element.removeEventListener("CssRuleViewChanged",
|
this.ruleView.element.removeEventListener("CssRuleViewChanged",
|
||||||
this.boundRuleViewChanged);
|
this.boundRuleViewChanged);
|
||||||
this.ruleView.element.removeEventListener("CssRuleViewCSSLinkClicked",
|
this.ruleView.element.removeEventListener("CssRuleViewCSSLinkClicked",
|
||||||
this.cssRuleViewBoundCSSLinkClicked);
|
this.cssRuleViewBoundCSSLinkClicked);
|
||||||
|
this.ruleView.element.removeEventListener("mousedown",
|
||||||
|
this.cssRuleViewBoundMouseDown);
|
||||||
|
this.ruleView.element.removeEventListener("mouseup",
|
||||||
|
this.cssRuleViewBoundMouseUp);
|
||||||
|
this.ruleView.element.removeEventListener("mousemove",
|
||||||
|
this.cssRuleViewBoundMouseMove);
|
||||||
delete boundRuleViewChanged;
|
delete boundRuleViewChanged;
|
||||||
this.ruleView.clear();
|
this.ruleView.clear();
|
||||||
delete this.ruleView;
|
delete this.ruleView;
|
||||||
@@ -1236,6 +1601,7 @@ InspectorUI.prototype = {
|
|||||||
iframe.id = "devtools-sidebar-iframe-" + aRegObj.id;
|
iframe.id = "devtools-sidebar-iframe-" + aRegObj.id;
|
||||||
iframe.setAttribute("flex", "1");
|
iframe.setAttribute("flex", "1");
|
||||||
iframe.setAttribute("tooltip", "aHTMLTooltip");
|
iframe.setAttribute("tooltip", "aHTMLTooltip");
|
||||||
|
iframe.addEventListener("mousedown", iframe.focus);
|
||||||
this.sidebarDeck.appendChild(iframe);
|
this.sidebarDeck.appendChild(iframe);
|
||||||
|
|
||||||
// wire up button to show the iframe
|
// wire up button to show the iframe
|
||||||
@@ -1347,6 +1713,10 @@ InspectorUI.prototype = {
|
|||||||
let btn = this.chromeDoc.getElementById(buttonId);
|
let btn = this.chromeDoc.getElementById(buttonId);
|
||||||
this.unbindToolEvent(btn, "click");
|
this.unbindToolEvent(btn, "click");
|
||||||
|
|
||||||
|
// Remove focus listener
|
||||||
|
let iframe = this.getToolIframe(aRegObj);
|
||||||
|
iframe.removeEventListener("mousedown", iframe.focus);
|
||||||
|
|
||||||
// remove sidebar buttons and tools
|
// remove sidebar buttons and tools
|
||||||
this.sidebarToolbar.removeChild(btn);
|
this.sidebarToolbar.removeChild(btn);
|
||||||
|
|
||||||
@@ -2232,3 +2602,17 @@ XPCOMUtils.defineLazyGetter(this, "StyleInspector", function () {
|
|||||||
XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
|
XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
|
||||||
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
|
||||||
|
return Cc["@mozilla.org/widget/clipboardhelper;1"].
|
||||||
|
getService(Ci.nsIClipboardHelper);
|
||||||
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "styleInspectorStrings", function() {
|
||||||
|
return Services.strings.createBundle(
|
||||||
|
"chrome://browser/locale/devtools/styleinspector.properties");
|
||||||
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "osString", function() {
|
||||||
|
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
|
||||||
|
});
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ _BROWSER_FILES = \
|
|||||||
browser_inspector_bug_665880.js \
|
browser_inspector_bug_665880.js \
|
||||||
browser_inspector_bug_674871.js \
|
browser_inspector_bug_674871.js \
|
||||||
browser_inspector_editor.js \
|
browser_inspector_editor.js \
|
||||||
|
browser_inspector_editor_name.js \
|
||||||
browser_inspector_bug_566084_location_changed.js \
|
browser_inspector_bug_566084_location_changed.js \
|
||||||
browser_inspector_infobar.js \
|
browser_inspector_infobar.js \
|
||||||
browser_inspector_bug_690361.js \
|
browser_inspector_bug_690361.js \
|
||||||
|
|||||||
@@ -3,13 +3,8 @@
|
|||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
*
|
* ***** END LICENSE BLOCK *****
|
||||||
* Contributor(s):
|
*/
|
||||||
* Rob Campbell <rcampbell@mozilla.com>
|
|
||||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
|
||||||
* Kyle Simpson <ksimpson@mozilla.com>
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
let doc;
|
let doc;
|
||||||
let div;
|
let div;
|
||||||
|
|||||||
@@ -0,0 +1,253 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
let doc;
|
||||||
|
let div;
|
||||||
|
let editorTestSteps;
|
||||||
|
|
||||||
|
function doNextStep() {
|
||||||
|
editorTestSteps.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupEditorTests()
|
||||||
|
{
|
||||||
|
div = doc.createElement("div");
|
||||||
|
div.setAttribute("id", "foobar");
|
||||||
|
div.setAttribute("class", "barbaz");
|
||||||
|
doc.body.appendChild(div);
|
||||||
|
|
||||||
|
Services.obs.addObserver(setupHTMLPanel, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||||
|
InspectorUI.toggleInspectorUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupHTMLPanel()
|
||||||
|
{
|
||||||
|
Services.obs.removeObserver(setupHTMLPanel, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
|
||||||
|
Services.obs.addObserver(runEditorTests, InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, false);
|
||||||
|
InspectorUI.toggleHTMLPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runEditorTests()
|
||||||
|
{
|
||||||
|
Services.obs.removeObserver(runEditorTests, InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY);
|
||||||
|
InspectorUI.stopInspecting();
|
||||||
|
InspectorUI.inspectNode(doc.body, true);
|
||||||
|
|
||||||
|
// setup generator for async test steps
|
||||||
|
editorTestSteps = doEditorTestSteps();
|
||||||
|
|
||||||
|
// add step listeners
|
||||||
|
Services.obs.addObserver(doNextStep, InspectorUI.INSPECTOR_NOTIFICATIONS.EDITOR_OPENED, false);
|
||||||
|
Services.obs.addObserver(doNextStep, InspectorUI.INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED, false);
|
||||||
|
Services.obs.addObserver(doNextStep, InspectorUI.INSPECTOR_NOTIFICATIONS.EDITOR_SAVED, false);
|
||||||
|
|
||||||
|
// start the tests
|
||||||
|
doNextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlighterTrap()
|
||||||
|
{
|
||||||
|
// bug 696107
|
||||||
|
InspectorUI.highlighter.removeListener("nodeselected", highlighterTrap);
|
||||||
|
ok(false, "Highlighter moved. Shouldn't be here!");
|
||||||
|
finishUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
function doEditorTestSteps()
|
||||||
|
{
|
||||||
|
let treePanel = InspectorUI.treePanel;
|
||||||
|
let editor = treePanel.treeBrowserDocument.getElementById("attribute-editor");
|
||||||
|
let editorInput = treePanel.treeBrowserDocument.getElementById("attribute-editor-input");
|
||||||
|
|
||||||
|
// Step 1: grab and test the attribute-name nodes in the HTML panel, then open editor
|
||||||
|
let nodes = treePanel.treeBrowserDocument.querySelectorAll(".nodeName.editable");
|
||||||
|
let attrNameNode_id = nodes[0]
|
||||||
|
let attrNameNode_class = nodes[1];
|
||||||
|
|
||||||
|
is(attrNameNode_id.innerHTML, "id", "Step 1: we have the correct `id` attribute-name node in the HTML panel");
|
||||||
|
is(attrNameNode_class.innerHTML, "class", "we have the correct `class` attribute-name node in the HTML panel");
|
||||||
|
|
||||||
|
// double-click the `id` attribute-name node to open the editor
|
||||||
|
executeSoon(function() {
|
||||||
|
// firing 2 clicks right in a row to simulate a double-click
|
||||||
|
EventUtils.synthesizeMouse(attrNameNode_id, 2, 2, {clickCount: 2}, attrNameNode_id.ownerDocument.defaultView);
|
||||||
|
});
|
||||||
|
|
||||||
|
yield; // End of Step 1
|
||||||
|
|
||||||
|
|
||||||
|
// Step 2: validate editing session, enter new attribute value into editor, and save input
|
||||||
|
ok(InspectorUI.treePanel.editingContext, "Step 2: editor session started");
|
||||||
|
let selection = InspectorUI.selection;
|
||||||
|
|
||||||
|
ok(selection, "Selection is: " + selection);
|
||||||
|
|
||||||
|
let editorVisible = editor.classList.contains("editing");
|
||||||
|
ok(editorVisible, "editor popup visible");
|
||||||
|
|
||||||
|
// check if the editor popup is "near" the correct position
|
||||||
|
let editorDims = editor.getBoundingClientRect();
|
||||||
|
let attrNameNodeDims = attrNameNode_id.getBoundingClientRect();
|
||||||
|
let editorPositionOK = (editorDims.left >= (attrNameNodeDims.left - editorDims.width - 5)) &&
|
||||||
|
(editorDims.right <= (attrNameNodeDims.right + editorDims.width + 5)) &&
|
||||||
|
(editorDims.top >= (attrNameNodeDims.top - editorDims.height - 5)) &&
|
||||||
|
(editorDims.bottom <= (attrNameNodeDims.bottom + editorDims.height + 5));
|
||||||
|
|
||||||
|
ok(editorPositionOK, "editor position acceptable");
|
||||||
|
|
||||||
|
// check to make sure the attribute-value node being edited is properly highlighted
|
||||||
|
let attrNameNodeHighlighted = attrNameNode_id.classList.contains("editingAttributeValue");
|
||||||
|
ok(attrNameNodeHighlighted, "`id` attribute-name node is editor-highlighted");
|
||||||
|
|
||||||
|
is(treePanel.editingContext.repObj, div, "editor session has correct reference to div");
|
||||||
|
is(treePanel.editingContext.attrObj, attrNameNode_id, "editor session has correct reference to `id` attribute-name node in HTML panel");
|
||||||
|
is(treePanel.editingContext.attrName, "id", "editor session knows correct attribute-name");
|
||||||
|
|
||||||
|
editorInput.value = "burp";
|
||||||
|
editorInput.focus();
|
||||||
|
|
||||||
|
InspectorUI.highlighter.addListener("nodeselected", highlighterTrap);
|
||||||
|
|
||||||
|
// hit <enter> to save the textbox value
|
||||||
|
executeSoon(function() {
|
||||||
|
// Extra key to test that keyboard handlers have been removed. bug 696107.
|
||||||
|
EventUtils.synthesizeKey("VK_LEFT", {}, attrNameNode_id.ownerDocument.defaultView);
|
||||||
|
EventUtils.synthesizeKey("VK_RETURN", {}, attrNameNode_id.ownerDocument.defaultView);
|
||||||
|
});
|
||||||
|
|
||||||
|
// two `yield` statements, to trap both the "SAVED" and "CLOSED" events that will be triggered
|
||||||
|
yield;
|
||||||
|
yield; // End of Step 2
|
||||||
|
|
||||||
|
// remove this from previous step
|
||||||
|
InspectorUI.highlighter.removeListener("nodeselected", highlighterTrap);
|
||||||
|
|
||||||
|
// Step 3: validate that the previous editing session saved correctly, then open editor on `class` attribute value
|
||||||
|
ok(!treePanel.editingContext, "Step 3: editor session ended");
|
||||||
|
editorVisible = editor.classList.contains("editing");
|
||||||
|
ok(!editorVisible, "editor popup hidden");
|
||||||
|
attrNameNodeHighlighted = attrNameNode_id.classList.contains("editingAttributeValue");
|
||||||
|
ok(!attrNameNodeHighlighted, "`id` attribute-value node is no longer editor-highlighted");
|
||||||
|
is(div.getAttribute("burp"), "foobar", "`id` attribute-name successfully updated");
|
||||||
|
is(attrNameNode_id.innerHTML, "burp", "attribute-name node in HTML panel successfully updated");
|
||||||
|
|
||||||
|
// double-click the `class` attribute-value node to open the editor
|
||||||
|
executeSoon(function() {
|
||||||
|
// firing 2 clicks right in a row to simulate a double-click
|
||||||
|
EventUtils.synthesizeMouse(attrNameNode_class, 2, 2, {clickCount: 2}, attrNameNode_class.ownerDocument.defaultView);
|
||||||
|
});
|
||||||
|
|
||||||
|
yield; // End of Step 3
|
||||||
|
|
||||||
|
|
||||||
|
// Step 4: enter value into editor, then hit <escape> to discard it
|
||||||
|
ok(treePanel.editingContext, "Step 4: editor session started");
|
||||||
|
editorVisible = editor.classList.contains("editing");
|
||||||
|
ok(editorVisible, "editor popup visible");
|
||||||
|
|
||||||
|
is(treePanel.editingContext.attrObj, attrNameNode_class, "editor session has correct reference to `class` attribute-name node in HTML panel");
|
||||||
|
is(treePanel.editingContext.attrName, "class", "editor session knows correct attribute-name");
|
||||||
|
|
||||||
|
editorInput.value = "Hello World";
|
||||||
|
editorInput.focus();
|
||||||
|
|
||||||
|
// hit <escape> to discard the inputted value
|
||||||
|
executeSoon(function() {
|
||||||
|
EventUtils.synthesizeKey("VK_ESCAPE", {}, attrNameNode_class.ownerDocument.defaultView);
|
||||||
|
});
|
||||||
|
|
||||||
|
yield; // End of Step 4
|
||||||
|
|
||||||
|
|
||||||
|
// Step 5: validate that the previous editing session discarded correctly, then open editor on `id` attribute value again
|
||||||
|
ok(!treePanel.editingContext, "Step 5: editor session ended");
|
||||||
|
editorVisible = editor.classList.contains("editing");
|
||||||
|
ok(!editorVisible, "editor popup hidden");
|
||||||
|
is(div.getAttribute("class"), "barbaz", "`class` attribute-name *not* updated");
|
||||||
|
is(attrNameNode_class.innerHTML, "class", "attribute-name node in HTML panel *not* updated");
|
||||||
|
|
||||||
|
// double-click the `id` attribute-name node to open the editor
|
||||||
|
executeSoon(function() {
|
||||||
|
// firing 2 clicks right in a row to simulate a double-click
|
||||||
|
EventUtils.synthesizeMouse(attrNameNode_id, 2, 2, {clickCount: 2}, attrNameNode_id.ownerDocument.defaultView);
|
||||||
|
});
|
||||||
|
|
||||||
|
yield; // End of Step 5
|
||||||
|
|
||||||
|
|
||||||
|
// Step 6: validate that editor opened again, then test double-click inside of editor (should do nothing)
|
||||||
|
ok(treePanel.editingContext, "Step 6: editor session started");
|
||||||
|
editorVisible = editor.classList.contains("editing");
|
||||||
|
ok(editorVisible, "editor popup visible");
|
||||||
|
|
||||||
|
// double-click on the editor input box
|
||||||
|
executeSoon(function() {
|
||||||
|
// firing 2 clicks right in a row to simulate a double-click
|
||||||
|
EventUtils.synthesizeMouse(editorInput, 2, 2, {clickCount: 2}, editorInput.ownerDocument.defaultView);
|
||||||
|
|
||||||
|
// since the previous double-click is supposed to do nothing,
|
||||||
|
// wait a brief moment, then move on to the next step
|
||||||
|
executeSoon(function() {
|
||||||
|
doNextStep();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
yield; // End of Step 6
|
||||||
|
|
||||||
|
|
||||||
|
// Step 7: validate that editing session is still correct, then enter a value and try a click
|
||||||
|
// outside of editor (should cancel the editing session)
|
||||||
|
ok(treePanel.editingContext, "Step 7: editor session still going");
|
||||||
|
editorVisible = editor.classList.contains("editing");
|
||||||
|
ok(editorVisible, "editor popup still visible");
|
||||||
|
|
||||||
|
editorInput.value = "all your base are belong to us";
|
||||||
|
|
||||||
|
// single-click the `class` attribute-value node
|
||||||
|
executeSoon(function() {
|
||||||
|
EventUtils.synthesizeMouse(attrNameNode_class, 2, 2, {}, attrNameNode_class.ownerDocument.defaultView);
|
||||||
|
});
|
||||||
|
|
||||||
|
yield; // End of Step 7
|
||||||
|
|
||||||
|
|
||||||
|
// Step 8: validate that the editor was closed and that the editing was not saved
|
||||||
|
ok(!treePanel.editingContext, "Step 8: editor session ended");
|
||||||
|
editorVisible = editor.classList.contains("editing");
|
||||||
|
ok(!editorVisible, "editor popup hidden");
|
||||||
|
is(div.getAttribute("burp"), "foobar", "`id` attribute-name *not* updated");
|
||||||
|
is(attrNameNode_id.innerHTML, "burp", "attribute-value node in HTML panel *not* updated");
|
||||||
|
|
||||||
|
// End of Step 8
|
||||||
|
executeSoon(finishUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishUp() {
|
||||||
|
// end of all steps, so clean up
|
||||||
|
Services.obs.removeObserver(doNextStep, InspectorUI.INSPECTOR_NOTIFICATIONS.EDITOR_OPENED, false);
|
||||||
|
Services.obs.removeObserver(doNextStep, InspectorUI.INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED, false);
|
||||||
|
Services.obs.removeObserver(doNextStep, InspectorUI.INSPECTOR_NOTIFICATIONS.EDITOR_SAVED, false);
|
||||||
|
doc = div = null;
|
||||||
|
InspectorUI.closeInspectorUI();
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
waitForExplicitFinish();
|
||||||
|
gBrowser.selectedTab = gBrowser.addTab();
|
||||||
|
gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||||
|
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||||
|
doc = content.document;
|
||||||
|
waitForFocus(setupEditorTests, content);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
content.location = "data:text/html,basic tests for html panel attribute-value editor";
|
||||||
|
}
|
||||||
|
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
- Rob Campbell <robcee@mozilla.com> (original author)
|
- Rob Campbell <robcee@mozilla.com> (original author)
|
||||||
- Mihai Sucan <mihai.sucan@gmail.com>
|
- Mihai Sucan <mihai.sucan@gmail.com>
|
||||||
- Erik Vold <erikvvold@gmail.com>
|
- Erik Vold <erikvvold@gmail.com>
|
||||||
|
- Mark Capella <markcapella@twcny.rr.com>
|
||||||
-
|
-
|
||||||
- Alternatively, the contents of this file may be used under the terms of
|
- Alternatively, the contents of this file may be used under the terms of
|
||||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ copy({
|
|||||||
ORION_EDITOR + "/orion/textview/rulers.js",
|
ORION_EDITOR + "/orion/textview/rulers.js",
|
||||||
ORION_EDITOR + "/orion/textview/undoStack.js",
|
ORION_EDITOR + "/orion/textview/undoStack.js",
|
||||||
ORION_EDITOR + "/orion/textview/textModel.js",
|
ORION_EDITOR + "/orion/textview/textModel.js",
|
||||||
|
ORION_EDITOR + "/orion/textview/projectionTextModel.js",
|
||||||
ORION_EDITOR + "/orion/textview/tooltip.js",
|
ORION_EDITOR + "/orion/textview/tooltip.js",
|
||||||
ORION_EDITOR + "/orion/textview/textView.js",
|
ORION_EDITOR + "/orion/textview/textView.js",
|
||||||
ORION_EDITOR + "/orion/textview/textDND.js",
|
ORION_EDITOR + "/orion/textview/textDND.js",
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ Orion version: git clone from 2012-01-26
|
|||||||
http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=27177e9a3dc70c20b4877e3eab3adfff1d56e342
|
http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=27177e9a3dc70c20b4877e3eab3adfff1d56e342
|
||||||
see https://bugs.eclipse.org/bugs/show_bug.cgi?id=370606
|
see https://bugs.eclipse.org/bugs/show_bug.cgi?id=370606
|
||||||
|
|
||||||
|
+ patch for Mozilla Bug 730532 - remove CSS2Properties aliases for MozOpacity
|
||||||
|
and MozOutline*
|
||||||
|
see https://bugzilla.mozilla.org/show_bug.cgi?id=730532#c3
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
The following files are licensed according to the contents in the LICENSE
|
The following files are licensed according to the contents in the LICENSE
|
||||||
|
|||||||
@@ -2563,6 +2563,590 @@ define("orion/textview/textModel", ['orion/textview/eventTarget'], function(mEve
|
|||||||
|
|
||||||
return {TextModel: TextModel};
|
return {TextModel: TextModel};
|
||||||
});/*******************************************************************************
|
});/*******************************************************************************
|
||||||
|
* @license
|
||||||
|
* Copyright (c) 2010, 2011 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials are made
|
||||||
|
* available under the terms of the Eclipse Public License v1.0
|
||||||
|
* (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
|
||||||
|
* License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Felipe Heidrich (IBM Corporation) - initial API and implementation
|
||||||
|
* Silenio Quarti (IBM Corporation) - initial API and implementation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*global define */
|
||||||
|
|
||||||
|
define("orion/textview/projectionTextModel", ['orion/textview/textModel', 'orion/textview/eventTarget'], function(mTextModel, mEventTarget) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class This object represents a projection range. A projection specifies a
|
||||||
|
* range of text and the replacement text. The range of text is relative to the
|
||||||
|
* base text model associated to a projection model.
|
||||||
|
* <p>
|
||||||
|
* <b>See:</b><br/>
|
||||||
|
* {@link orion.textview.ProjectionTextModel}<br/>
|
||||||
|
* {@link orion.textview.ProjectionTextModel#addProjection}<br/>
|
||||||
|
* </p>
|
||||||
|
* @name orion.textview.Projection
|
||||||
|
*
|
||||||
|
* @property {Number} start The start offset of the projection range.
|
||||||
|
* @property {Number} end The end offset of the projection range. This offset is exclusive.
|
||||||
|
* @property {String|orion.textview.TextModel} [text=""] The projection text to be inserted
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Constructs a new <code>ProjectionTextModel</code> based on the specified <code>TextModel</code>.
|
||||||
|
*
|
||||||
|
* @param {orion.textview.TextModel} baseModel The base text model.
|
||||||
|
*
|
||||||
|
* @name orion.textview.ProjectionTextModel
|
||||||
|
* @class The <code>ProjectionTextModel</code> represents a projection of its base text
|
||||||
|
* model. Projection ranges can be added to the projection text model to hide and/or insert
|
||||||
|
* ranges to the base text model.
|
||||||
|
* <p>
|
||||||
|
* The contents of the projection text model is modified when changes occur in the base model,
|
||||||
|
* projection model or by calls to {@link #addProjection} and {@link #removeProjection}.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* <b>See:</b><br/>
|
||||||
|
* {@link orion.textview.TextView}<br/>
|
||||||
|
* {@link orion.textview.TextModel}
|
||||||
|
* {@link orion.textview.TextView#setModel}
|
||||||
|
* </p>
|
||||||
|
* @borrows orion.textview.EventTarget#addEventListener as #addEventListener
|
||||||
|
* @borrows orion.textview.EventTarget#removeEventListener as #removeEventListener
|
||||||
|
* @borrows orion.textview.EventTarget#dispatchEvent as #dispatchEvent
|
||||||
|
*/
|
||||||
|
function ProjectionTextModel(baseModel) {
|
||||||
|
this._model = baseModel; /* Base Model */
|
||||||
|
this._projections = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectionTextModel.prototype = /** @lends orion.textview.ProjectionTextModel.prototype */ {
|
||||||
|
/**
|
||||||
|
* Adds a projection range to the model.
|
||||||
|
* <p>
|
||||||
|
* The model must notify the listeners before and after the the text is
|
||||||
|
* changed by calling {@link #onChanging} and {@link #onChanged} respectively.
|
||||||
|
* </p>
|
||||||
|
* @param {orion.textview.Projection} projection The projection range to be added.
|
||||||
|
*
|
||||||
|
* @see #removeProjection
|
||||||
|
*/
|
||||||
|
addProjection: function(projection) {
|
||||||
|
if (!projection) {return;}
|
||||||
|
//start and end can't overlap any exist projection
|
||||||
|
var model = this._model, projections = this._projections;
|
||||||
|
projection._lineIndex = model.getLineAtOffset(projection.start);
|
||||||
|
projection._lineCount = model.getLineAtOffset(projection.end) - projection._lineIndex;
|
||||||
|
var text = projection.text;
|
||||||
|
if (!text) { text = ""; }
|
||||||
|
if (typeof text === "string") {
|
||||||
|
projection._model = new mTextModel.TextModel(text, model.getLineDelimiter());
|
||||||
|
} else {
|
||||||
|
projection._model = text;
|
||||||
|
}
|
||||||
|
var eventStart = this.mapOffset(projection.start, true);
|
||||||
|
var removedCharCount = projection.end - projection.start;
|
||||||
|
var removedLineCount = projection._lineCount;
|
||||||
|
var addedCharCount = projection._model.getCharCount();
|
||||||
|
var addedLineCount = projection._model.getLineCount() - 1;
|
||||||
|
var modelChangingEvent = {
|
||||||
|
type: "Changing",
|
||||||
|
text: projection._model.getText(),
|
||||||
|
start: eventStart,
|
||||||
|
removedCharCount: removedCharCount,
|
||||||
|
addedCharCount: addedCharCount,
|
||||||
|
removedLineCount: removedLineCount,
|
||||||
|
addedLineCount: addedLineCount
|
||||||
|
};
|
||||||
|
this.onChanging(modelChangingEvent);
|
||||||
|
var index = this._binarySearch(projections, projection.start);
|
||||||
|
projections.splice(index, 0, projection);
|
||||||
|
var modelChangedEvent = {
|
||||||
|
type: "Changed",
|
||||||
|
start: eventStart,
|
||||||
|
removedCharCount: removedCharCount,
|
||||||
|
addedCharCount: addedCharCount,
|
||||||
|
removedLineCount: removedLineCount,
|
||||||
|
addedLineCount: addedLineCount
|
||||||
|
};
|
||||||
|
this.onChanged(modelChangedEvent);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Returns all projection ranges of this model.
|
||||||
|
*
|
||||||
|
* @return {orion.textview.Projection[]} The projection ranges.
|
||||||
|
*
|
||||||
|
* @see #addProjection
|
||||||
|
*/
|
||||||
|
getProjections: function() {
|
||||||
|
return this._projections.slice(0);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Gets the base text model.
|
||||||
|
*
|
||||||
|
* @return {orion.textview.TextModel} The base text model.
|
||||||
|
*/
|
||||||
|
getBaseModel: function() {
|
||||||
|
return this._model;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Maps offsets between the projection model and its base model.
|
||||||
|
*
|
||||||
|
* @param {Number} offset The offset to be mapped.
|
||||||
|
* @param {Boolean} [baseOffset=false] <code>true</code> if <code>offset</code> is in base model and
|
||||||
|
* should be mapped to the projection model.
|
||||||
|
* @return {Number} The mapped offset
|
||||||
|
*/
|
||||||
|
mapOffset: function(offset, baseOffset) {
|
||||||
|
var projections = this._projections, delta = 0, i, projection;
|
||||||
|
if (baseOffset) {
|
||||||
|
for (i = 0; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
if (projection.start > offset) { break; }
|
||||||
|
if (projection.end > offset) { return -1; }
|
||||||
|
delta += projection._model.getCharCount() - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
return offset + delta;
|
||||||
|
}
|
||||||
|
for (i = 0; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
if (projection.start > offset - delta) { break; }
|
||||||
|
var charCount = projection._model.getCharCount();
|
||||||
|
if (projection.start + charCount > offset - delta) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
delta += charCount - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
return offset - delta;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Removes a projection range from the model.
|
||||||
|
* <p>
|
||||||
|
* The model must notify the listeners before and after the the text is
|
||||||
|
* changed by calling {@link #onChanging} and {@link #onChanged} respectively.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param {orion.textview.Projection} projection The projection range to be removed.
|
||||||
|
*
|
||||||
|
* @see #addProjection
|
||||||
|
*/
|
||||||
|
removeProjection: function(projection) {
|
||||||
|
//TODO remove listeners from model
|
||||||
|
var i, delta = 0;
|
||||||
|
for (i = 0; i < this._projections.length; i++) {
|
||||||
|
var p = this._projections[i];
|
||||||
|
if (p === projection) {
|
||||||
|
projection = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delta += p._model.getCharCount() - (p.end - p.start);
|
||||||
|
}
|
||||||
|
if (i < this._projections.length) {
|
||||||
|
var model = this._model;
|
||||||
|
var eventStart = projection.start + delta;
|
||||||
|
var addedCharCount = projection.end - projection.start;
|
||||||
|
var addedLineCount = projection._lineCount;
|
||||||
|
var removedCharCount = projection._model.getCharCount();
|
||||||
|
var removedLineCount = projection._model.getLineCount() - 1;
|
||||||
|
var modelChangingEvent = {
|
||||||
|
type: "Changing",
|
||||||
|
text: model.getText(projection.start, projection.end),
|
||||||
|
start: eventStart,
|
||||||
|
removedCharCount: removedCharCount,
|
||||||
|
addedCharCount: addedCharCount,
|
||||||
|
removedLineCount: removedLineCount,
|
||||||
|
addedLineCount: addedLineCount
|
||||||
|
};
|
||||||
|
this.onChanging(modelChangingEvent);
|
||||||
|
this._projections.splice(i, 1);
|
||||||
|
var modelChangedEvent = {
|
||||||
|
type: "Changed",
|
||||||
|
start: eventStart,
|
||||||
|
removedCharCount: removedCharCount,
|
||||||
|
addedCharCount: addedCharCount,
|
||||||
|
removedLineCount: removedLineCount,
|
||||||
|
addedLineCount: addedLineCount
|
||||||
|
};
|
||||||
|
this.onChanged(modelChangedEvent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** @ignore */
|
||||||
|
_binarySearch: function (array, offset) {
|
||||||
|
var high = array.length, low = -1, index;
|
||||||
|
while (high - low > 1) {
|
||||||
|
index = Math.floor((high + low) / 2);
|
||||||
|
if (offset <= array[index].start) {
|
||||||
|
high = index;
|
||||||
|
} else {
|
||||||
|
low = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return high;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#getCharCount
|
||||||
|
*/
|
||||||
|
getCharCount: function() {
|
||||||
|
var count = this._model.getCharCount(), projections = this._projections;
|
||||||
|
for (var i = 0; i < projections.length; i++) {
|
||||||
|
var projection = projections[i];
|
||||||
|
count += projection._model.getCharCount() - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#getLine
|
||||||
|
*/
|
||||||
|
getLine: function(lineIndex, includeDelimiter) {
|
||||||
|
if (lineIndex < 0) { return null; }
|
||||||
|
var model = this._model, projections = this._projections;
|
||||||
|
var delta = 0, result = [], offset = 0, i, lineCount, projection;
|
||||||
|
for (i = 0; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
if (projection._lineIndex >= lineIndex - delta) { break; }
|
||||||
|
lineCount = projection._model.getLineCount() - 1;
|
||||||
|
if (projection._lineIndex + lineCount >= lineIndex - delta) {
|
||||||
|
var projectionLineIndex = lineIndex - (projection._lineIndex + delta);
|
||||||
|
if (projectionLineIndex < lineCount) {
|
||||||
|
return projection._model.getLine(projectionLineIndex, includeDelimiter);
|
||||||
|
} else {
|
||||||
|
result.push(projection._model.getLine(lineCount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset = projection.end;
|
||||||
|
delta += lineCount - projection._lineCount;
|
||||||
|
}
|
||||||
|
offset = Math.max(offset, model.getLineStart(lineIndex - delta));
|
||||||
|
for (; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
if (projection._lineIndex > lineIndex - delta) { break; }
|
||||||
|
result.push(model.getText(offset, projection.start));
|
||||||
|
lineCount = projection._model.getLineCount() - 1;
|
||||||
|
if (projection._lineIndex + lineCount > lineIndex - delta) {
|
||||||
|
result.push(projection._model.getLine(0, includeDelimiter));
|
||||||
|
return result.join("");
|
||||||
|
}
|
||||||
|
result.push(projection._model.getText());
|
||||||
|
offset = projection.end;
|
||||||
|
delta += lineCount - projection._lineCount;
|
||||||
|
}
|
||||||
|
var end = model.getLineEnd(lineIndex - delta, includeDelimiter);
|
||||||
|
if (offset < end) {
|
||||||
|
result.push(model.getText(offset, end));
|
||||||
|
}
|
||||||
|
return result.join("");
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#getLineAtOffset
|
||||||
|
*/
|
||||||
|
getLineAtOffset: function(offset) {
|
||||||
|
var model = this._model, projections = this._projections;
|
||||||
|
var delta = 0, lineDelta = 0;
|
||||||
|
for (var i = 0; i < projections.length; i++) {
|
||||||
|
var projection = projections[i];
|
||||||
|
if (projection.start > offset - delta) { break; }
|
||||||
|
var charCount = projection._model.getCharCount();
|
||||||
|
if (projection.start + charCount > offset - delta) {
|
||||||
|
var projectionOffset = offset - (projection.start + delta);
|
||||||
|
lineDelta += projection._model.getLineAtOffset(projectionOffset);
|
||||||
|
delta += projectionOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lineDelta += projection._model.getLineCount() - 1 - projection._lineCount;
|
||||||
|
delta += charCount - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
return model.getLineAtOffset(offset - delta) + lineDelta;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#getLineCount
|
||||||
|
*/
|
||||||
|
getLineCount: function() {
|
||||||
|
var model = this._model, projections = this._projections;
|
||||||
|
var count = model.getLineCount();
|
||||||
|
for (var i = 0; i < projections.length; i++) {
|
||||||
|
var projection = projections[i];
|
||||||
|
count += projection._model.getLineCount() - 1 - projection._lineCount;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#getLineDelimiter
|
||||||
|
*/
|
||||||
|
getLineDelimiter: function() {
|
||||||
|
return this._model.getLineDelimiter();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#getLineEnd
|
||||||
|
*/
|
||||||
|
getLineEnd: function(lineIndex, includeDelimiter) {
|
||||||
|
if (lineIndex < 0) { return -1; }
|
||||||
|
var model = this._model, projections = this._projections;
|
||||||
|
var delta = 0, offsetDelta = 0;
|
||||||
|
for (var i = 0; i < projections.length; i++) {
|
||||||
|
var projection = projections[i];
|
||||||
|
if (projection._lineIndex > lineIndex - delta) { break; }
|
||||||
|
var lineCount = projection._model.getLineCount() - 1;
|
||||||
|
if (projection._lineIndex + lineCount > lineIndex - delta) {
|
||||||
|
var projectionLineIndex = lineIndex - (projection._lineIndex + delta);
|
||||||
|
return projection._model.getLineEnd (projectionLineIndex, includeDelimiter) + projection.start + offsetDelta;
|
||||||
|
}
|
||||||
|
offsetDelta += projection._model.getCharCount() - (projection.end - projection.start);
|
||||||
|
delta += lineCount - projection._lineCount;
|
||||||
|
}
|
||||||
|
return model.getLineEnd(lineIndex - delta, includeDelimiter) + offsetDelta;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#getLineStart
|
||||||
|
*/
|
||||||
|
getLineStart: function(lineIndex) {
|
||||||
|
if (lineIndex < 0) { return -1; }
|
||||||
|
var model = this._model, projections = this._projections;
|
||||||
|
var delta = 0, offsetDelta = 0;
|
||||||
|
for (var i = 0; i < projections.length; i++) {
|
||||||
|
var projection = projections[i];
|
||||||
|
if (projection._lineIndex >= lineIndex - delta) { break; }
|
||||||
|
var lineCount = projection._model.getLineCount() - 1;
|
||||||
|
if (projection._lineIndex + lineCount >= lineIndex - delta) {
|
||||||
|
var projectionLineIndex = lineIndex - (projection._lineIndex + delta);
|
||||||
|
return projection._model.getLineStart (projectionLineIndex) + projection.start + offsetDelta;
|
||||||
|
}
|
||||||
|
offsetDelta += projection._model.getCharCount() - (projection.end - projection.start);
|
||||||
|
delta += lineCount - projection._lineCount;
|
||||||
|
}
|
||||||
|
return model.getLineStart(lineIndex - delta) + offsetDelta;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#getText
|
||||||
|
*/
|
||||||
|
getText: function(start, end) {
|
||||||
|
if (start === undefined) { start = 0; }
|
||||||
|
var model = this._model, projections = this._projections;
|
||||||
|
var delta = 0, result = [], i, projection, charCount;
|
||||||
|
for (i = 0; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
if (projection.start > start - delta) { break; }
|
||||||
|
charCount = projection._model.getCharCount();
|
||||||
|
if (projection.start + charCount > start - delta) {
|
||||||
|
if (end !== undefined && projection.start + charCount > end - delta) {
|
||||||
|
return projection._model.getText(start - (projection.start + delta), end - (projection.start + delta));
|
||||||
|
} else {
|
||||||
|
result.push(projection._model.getText(start - (projection.start + delta)));
|
||||||
|
start = projection.end + delta + charCount - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delta += charCount - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
var offset = start - delta;
|
||||||
|
if (end !== undefined) {
|
||||||
|
for (; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
if (projection.start > end - delta) { break; }
|
||||||
|
result.push(model.getText(offset, projection.start));
|
||||||
|
charCount = projection._model.getCharCount();
|
||||||
|
if (projection.start + charCount > end - delta) {
|
||||||
|
result.push(projection._model.getText(0, end - (projection.start + delta)));
|
||||||
|
return result.join("");
|
||||||
|
}
|
||||||
|
result.push(projection._model.getText());
|
||||||
|
offset = projection.end;
|
||||||
|
delta += charCount - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
result.push(model.getText(offset, end - delta));
|
||||||
|
} else {
|
||||||
|
for (; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
result.push(model.getText(offset, projection.start));
|
||||||
|
result.push(projection._model.getText());
|
||||||
|
offset = projection.end;
|
||||||
|
}
|
||||||
|
result.push(model.getText(offset));
|
||||||
|
}
|
||||||
|
return result.join("");
|
||||||
|
},
|
||||||
|
/** @ignore */
|
||||||
|
_onChanging: function(text, start, removedCharCount, addedCharCount, removedLineCount, addedLineCount) {
|
||||||
|
var model = this._model, projections = this._projections, i, projection, delta = 0, lineDelta;
|
||||||
|
var end = start + removedCharCount;
|
||||||
|
for (; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
if (projection.start > start) { break; }
|
||||||
|
delta += projection._model.getCharCount() - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
/*TODO add stuff saved by setText*/
|
||||||
|
var mapStart = start + delta, rangeStart = i;
|
||||||
|
for (; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
if (projection.start > end) { break; }
|
||||||
|
delta += projection._model.getCharCount() - (projection.end - projection.start);
|
||||||
|
lineDelta += projection._model.getLineCount() - 1 - projection._lineCount;
|
||||||
|
}
|
||||||
|
/*TODO add stuff saved by setText*/
|
||||||
|
var mapEnd = end + delta, rangeEnd = i;
|
||||||
|
this.onChanging(mapStart, mapEnd - mapStart, addedCharCount/*TODO add stuff saved by setText*/, removedLineCount + lineDelta/*TODO add stuff saved by setText*/, addedLineCount/*TODO add stuff saved by setText*/);
|
||||||
|
projections.splice(projections, rangeEnd - rangeStart);
|
||||||
|
var count = text.length - (mapEnd - mapStart);
|
||||||
|
for (; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
projection.start += count;
|
||||||
|
projection.end += count;
|
||||||
|
projection._lineIndex = model.getLineAtOffset(projection.start);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#onChanging
|
||||||
|
*/
|
||||||
|
onChanging: function(modelChangingEvent) {
|
||||||
|
return this.dispatchEvent(modelChangingEvent);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#onChanged
|
||||||
|
*/
|
||||||
|
onChanged: function(modelChangedEvent) {
|
||||||
|
return this.dispatchEvent(modelChangedEvent);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#setLineDelimiter
|
||||||
|
*/
|
||||||
|
setLineDelimiter: function(lineDelimiter) {
|
||||||
|
this._model.setLineDelimiter(lineDelimiter);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @see orion.textview.TextModel#setText
|
||||||
|
*/
|
||||||
|
setText: function(text, start, end) {
|
||||||
|
if (text === undefined) { text = ""; }
|
||||||
|
if (start === undefined) { start = 0; }
|
||||||
|
var eventStart = start, eventEnd = end;
|
||||||
|
var model = this._model, projections = this._projections;
|
||||||
|
var delta = 0, lineDelta = 0, i, projection, charCount, startProjection, endProjection, startLineDelta = 0;
|
||||||
|
for (i = 0; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
if (projection.start > start - delta) { break; }
|
||||||
|
charCount = projection._model.getCharCount();
|
||||||
|
if (projection.start + charCount > start - delta) {
|
||||||
|
if (end !== undefined && projection.start + charCount > end - delta) {
|
||||||
|
projection._model.setText(text, start - (projection.start + delta), end - (projection.start + delta));
|
||||||
|
//TODO events - special case
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
startLineDelta = projection._model.getLineCount() - 1 - projection._model.getLineAtOffset(start - (projection.start + delta));
|
||||||
|
startProjection = {
|
||||||
|
projection: projection,
|
||||||
|
start: start - (projection.start + delta)
|
||||||
|
};
|
||||||
|
start = projection.end + delta + charCount - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lineDelta += projection._model.getLineCount() - 1 - projection._lineCount;
|
||||||
|
delta += charCount - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
var mapStart = start - delta, rangeStart = i, startLine = model.getLineAtOffset(mapStart) + lineDelta - startLineDelta;
|
||||||
|
if (end !== undefined) {
|
||||||
|
for (; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
if (projection.start > end - delta) { break; }
|
||||||
|
charCount = projection._model.getCharCount();
|
||||||
|
if (projection.start + charCount > end - delta) {
|
||||||
|
lineDelta += projection._model.getLineAtOffset(end - (projection.start + delta));
|
||||||
|
charCount = end - (projection.start + delta);
|
||||||
|
end = projection.end + delta;
|
||||||
|
endProjection = {
|
||||||
|
projection: projection,
|
||||||
|
end: charCount
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lineDelta += projection._model.getLineCount() - 1 - projection._lineCount;
|
||||||
|
delta += charCount - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
lineDelta += projection._model.getLineCount() - 1 - projection._lineCount;
|
||||||
|
delta += projection._model.getCharCount() - (projection.end - projection.start);
|
||||||
|
}
|
||||||
|
end = eventEnd = model.getCharCount() + delta;
|
||||||
|
}
|
||||||
|
var mapEnd = end - delta, rangeEnd = i, endLine = model.getLineAtOffset(mapEnd) + lineDelta;
|
||||||
|
|
||||||
|
//events
|
||||||
|
var removedCharCount = eventEnd - eventStart;
|
||||||
|
var removedLineCount = endLine - startLine;
|
||||||
|
var addedCharCount = text.length;
|
||||||
|
var addedLineCount = 0;
|
||||||
|
var cr = 0, lf = 0, index = 0;
|
||||||
|
while (true) {
|
||||||
|
if (cr !== -1 && cr <= index) { cr = text.indexOf("\r", index); }
|
||||||
|
if (lf !== -1 && lf <= index) { lf = text.indexOf("\n", index); }
|
||||||
|
if (lf === -1 && cr === -1) { break; }
|
||||||
|
if (cr !== -1 && lf !== -1) {
|
||||||
|
if (cr + 1 === lf) {
|
||||||
|
index = lf + 1;
|
||||||
|
} else {
|
||||||
|
index = (cr < lf ? cr : lf) + 1;
|
||||||
|
}
|
||||||
|
} else if (cr !== -1) {
|
||||||
|
index = cr + 1;
|
||||||
|
} else {
|
||||||
|
index = lf + 1;
|
||||||
|
}
|
||||||
|
addedLineCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var modelChangingEvent = {
|
||||||
|
type: "Changing",
|
||||||
|
text: text,
|
||||||
|
start: eventStart,
|
||||||
|
removedCharCount: removedCharCount,
|
||||||
|
addedCharCount: addedCharCount,
|
||||||
|
removedLineCount: removedLineCount,
|
||||||
|
addedLineCount: addedLineCount
|
||||||
|
};
|
||||||
|
this.onChanging(modelChangingEvent);
|
||||||
|
|
||||||
|
// var changeLineCount = model.getLineAtOffset(mapEnd) - model.getLineAtOffset(mapStart) + addedLineCount;
|
||||||
|
model.setText(text, mapStart, mapEnd);
|
||||||
|
if (startProjection) {
|
||||||
|
projection = startProjection.projection;
|
||||||
|
projection._model.setText("", startProjection.start);
|
||||||
|
}
|
||||||
|
if (endProjection) {
|
||||||
|
projection = endProjection.projection;
|
||||||
|
projection._model.setText("", 0, endProjection.end);
|
||||||
|
projection.start = projection.end;
|
||||||
|
projection._lineCount = 0;
|
||||||
|
}
|
||||||
|
projections.splice(rangeStart, rangeEnd - rangeStart);
|
||||||
|
var changeCount = text.length - (mapEnd - mapStart);
|
||||||
|
for (i = rangeEnd; i < projections.length; i++) {
|
||||||
|
projection = projections[i];
|
||||||
|
projection.start += changeCount;
|
||||||
|
projection.end += changeCount;
|
||||||
|
// if (projection._lineIndex + changeLineCount !== model.getLineAtOffset(projection.start)) {
|
||||||
|
// log("here");
|
||||||
|
// }
|
||||||
|
projection._lineIndex = model.getLineAtOffset(projection.start);
|
||||||
|
// projection._lineIndex += changeLineCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
var modelChangedEvent = {
|
||||||
|
type: "Changed",
|
||||||
|
start: eventStart,
|
||||||
|
removedCharCount: removedCharCount,
|
||||||
|
addedCharCount: addedCharCount,
|
||||||
|
removedLineCount: removedLineCount,
|
||||||
|
addedLineCount: addedLineCount
|
||||||
|
};
|
||||||
|
this.onChanged(modelChangedEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mEventTarget.EventTarget.addMixin(ProjectionTextModel.prototype);
|
||||||
|
|
||||||
|
return {ProjectionTextModel: ProjectionTextModel};
|
||||||
|
});
|
||||||
|
/*******************************************************************************
|
||||||
* @license
|
* @license
|
||||||
* Copyright (c) 2010, 2011 IBM Corporation and others.
|
* Copyright (c) 2010, 2011 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials are made
|
* All rights reserved. This program and the accompanying materials are made
|
||||||
|
|||||||
@@ -908,7 +908,8 @@ SourceEditor.prototype = {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param string aType
|
* @param string aType
|
||||||
* The annotation type to filter annotations for.
|
* The annotation type to filter annotations for. Use one of the keys
|
||||||
|
* in ORION_ANNOTATION_TYPES.
|
||||||
* @param number aStart
|
* @param number aStart
|
||||||
* Offset from where to start finding the annotations.
|
* Offset from where to start finding the annotations.
|
||||||
* @param number aEnd
|
* @param number aEnd
|
||||||
|
|||||||
@@ -268,24 +268,24 @@ SourceEditor.EVENTS = {
|
|||||||
BLUR: "Blur",
|
BLUR: "Blur",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The MouseMove event is sent when the user moves the mouse over a line
|
* The MouseMove event is sent when the user moves the mouse over a line.
|
||||||
* annotation. The event object properties:
|
* The event object properties:
|
||||||
* - event - the DOM mousemove event object.
|
* - event - the DOM mousemove event object.
|
||||||
* - x and y - the mouse coordinates relative to the document being edited.
|
* - x and y - the mouse coordinates relative to the document being edited.
|
||||||
*/
|
*/
|
||||||
MOUSE_MOVE: "MouseMove",
|
MOUSE_MOVE: "MouseMove",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The MouseOver event is sent when the mouse pointer enters a line
|
* The MouseOver event is sent when the mouse pointer enters a line.
|
||||||
* annotation. The event object properties:
|
* The event object properties:
|
||||||
* - event - the DOM mouseover event object.
|
* - event - the DOM mouseover event object.
|
||||||
* - x and y - the mouse coordinates relative to the document being edited.
|
* - x and y - the mouse coordinates relative to the document being edited.
|
||||||
*/
|
*/
|
||||||
MOUSE_OVER: "MouseOver",
|
MOUSE_OVER: "MouseOver",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This MouseOut event is sent when the mouse pointer exits a line
|
* This MouseOut event is sent when the mouse pointer exits a line.
|
||||||
* annotation. The event object properties:
|
* The event object properties:
|
||||||
* - event - the DOM mouseout event object.
|
* - event - the DOM mouseout event object.
|
||||||
* - x and y - the mouse coordinates relative to the document being edited.
|
* - x and y - the mouse coordinates relative to the document being edited.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
|
const Cc = Components.classes;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
const FILTER_CHANGED_TIMEOUT = 300;
|
const FILTER_CHANGED_TIMEOUT = 300;
|
||||||
|
|
||||||
@@ -161,9 +162,18 @@ function CssHtmlTree(aStyleInspector)
|
|||||||
this.getRTLAttr = this.win.getComputedStyle(this.win.gBrowser).direction;
|
this.getRTLAttr = this.win.getComputedStyle(this.win.gBrowser).direction;
|
||||||
this.propertyViews = [];
|
this.propertyViews = [];
|
||||||
|
|
||||||
|
// Create bound methods.
|
||||||
|
this.siBoundMenuUpdate = this.computedViewMenuUpdate.bind(this);
|
||||||
|
this.siBoundCopy = this.computedViewCopy.bind(this);
|
||||||
|
this.siBoundCopyDeclaration = this.computedViewCopyDeclaration.bind(this);
|
||||||
|
this.siBoundCopyProperty = this.computedViewCopyProperty.bind(this);
|
||||||
|
this.siBoundCopyPropertyValue = this.computedViewCopyPropertyValue.bind(this);
|
||||||
|
|
||||||
// The document in which we display the results (csshtmltree.xul).
|
// The document in which we display the results (csshtmltree.xul).
|
||||||
this.styleDocument = this.styleWin.contentWindow.document;
|
this.styleDocument = this.styleWin.contentWindow.document;
|
||||||
|
|
||||||
|
this.styleDocument.addEventListener("copy", this.siBoundCopy);
|
||||||
|
|
||||||
// Nodes used in templating
|
// Nodes used in templating
|
||||||
this.root = this.styleDocument.getElementById("root");
|
this.root = this.styleDocument.getElementById("root");
|
||||||
this.templateRoot = this.styleDocument.getElementById("templateRoot");
|
this.templateRoot = this.styleDocument.getElementById("templateRoot");
|
||||||
@@ -176,6 +186,7 @@ function CssHtmlTree(aStyleInspector)
|
|||||||
// The element that we're inspecting, and the document that it comes from.
|
// The element that we're inspecting, and the document that it comes from.
|
||||||
this.viewedElement = null;
|
this.viewedElement = null;
|
||||||
this.createStyleViews();
|
this.createStyleViews();
|
||||||
|
this.createContextMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -231,6 +242,11 @@ XPCOMUtils.defineLazyGetter(CssHtmlTree, "HELP_LINK_TITLE", function() {
|
|||||||
return CssHtmlTree.HELP_LINK_TITLE = CssHtmlTree.l10n("helpLinkTitle");
|
return CssHtmlTree.HELP_LINK_TITLE = CssHtmlTree.l10n("helpLinkTitle");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() {
|
||||||
|
return Cc["@mozilla.org/widget/clipboardhelper;1"].
|
||||||
|
getService(Ci.nsIClipboardHelper);
|
||||||
|
});
|
||||||
|
|
||||||
CssHtmlTree.prototype = {
|
CssHtmlTree.prototype = {
|
||||||
// Cache the list of properties that have matched and unmatched properties.
|
// Cache the list of properties that have matched and unmatched properties.
|
||||||
_matchedProperties: null,
|
_matchedProperties: null,
|
||||||
@@ -469,6 +485,177 @@ CssHtmlTree.prototype = {
|
|||||||
return this._unmatchedProperties[aProperty];
|
return this._unmatchedProperties[aProperty];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a context menu.
|
||||||
|
*/
|
||||||
|
createContextMenu: function SI_createContextMenu()
|
||||||
|
{
|
||||||
|
let popupSet = this.doc.getElementById("mainPopupSet");
|
||||||
|
|
||||||
|
let menu = this.doc.createElement("menupopup");
|
||||||
|
menu.addEventListener("popupshowing", this.siBoundMenuUpdate);
|
||||||
|
menu.id = "computed-view-context-menu";
|
||||||
|
popupSet.appendChild(menu);
|
||||||
|
|
||||||
|
// Copy selection
|
||||||
|
let label = CssHtmlTree.l10n("style.contextmenu.copyselection");
|
||||||
|
let accessKey = CssHtmlTree.l10n("style.contextmenu.copyselection.accesskey");
|
||||||
|
let item = this.doc.createElement("menuitem");
|
||||||
|
item.id = "computed-view-copy";
|
||||||
|
item.setAttribute("label", label);
|
||||||
|
item.setAttribute("accesskey", accessKey);
|
||||||
|
item.addEventListener("command", this.siBoundCopy);
|
||||||
|
menu.appendChild(item);
|
||||||
|
|
||||||
|
// Copy declaration
|
||||||
|
label = CssHtmlTree.l10n("style.contextmenu.copydeclaration");
|
||||||
|
accessKey = CssHtmlTree.l10n("style.contextmenu.copydeclaration.accesskey");
|
||||||
|
item = this.doc.createElement("menuitem");
|
||||||
|
item.id = "computed-view-copy-declaration";
|
||||||
|
item.setAttribute("label", label);
|
||||||
|
item.setAttribute("accesskey", accessKey);
|
||||||
|
item.addEventListener("command", this.siBoundCopyDeclaration);
|
||||||
|
menu.appendChild(item);
|
||||||
|
|
||||||
|
// Copy property name
|
||||||
|
label = CssHtmlTree.l10n("style.contextmenu.copyproperty");
|
||||||
|
accessKey = CssHtmlTree.l10n("style.contextmenu.copyproperty.accesskey");
|
||||||
|
item = this.doc.createElement("menuitem");
|
||||||
|
item.id = "computed-view-copy-property";
|
||||||
|
item.setAttribute("label", label);
|
||||||
|
item.setAttribute("accesskey", accessKey);
|
||||||
|
item.addEventListener("command", this.siBoundCopyProperty);
|
||||||
|
menu.appendChild(item);
|
||||||
|
|
||||||
|
// Copy property value
|
||||||
|
label = CssHtmlTree.l10n("style.contextmenu.copypropertyvalue");
|
||||||
|
accessKey = CssHtmlTree.l10n("style.contextmenu.copypropertyvalue.accesskey");
|
||||||
|
item = this.doc.createElement("menuitem");
|
||||||
|
item.id = "computed-view-copy-property-value";
|
||||||
|
item.setAttribute("label", label);
|
||||||
|
item.setAttribute("accesskey", accessKey);
|
||||||
|
item.addEventListener("command", this.siBoundCopyPropertyValue);
|
||||||
|
menu.appendChild(item);
|
||||||
|
|
||||||
|
this.styleWin.setAttribute("context", menu.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the context menu by disabling irrelevant menuitems and enabling
|
||||||
|
* relevant ones.
|
||||||
|
*/
|
||||||
|
computedViewMenuUpdate: function si_computedViewMenuUpdate()
|
||||||
|
{
|
||||||
|
let win = this.styleDocument.defaultView;
|
||||||
|
let disable = win.getSelection().isCollapsed;
|
||||||
|
let menuitem = this.doc.querySelector("#computed-view-copy");
|
||||||
|
menuitem.disabled = disable;
|
||||||
|
|
||||||
|
let node = this.doc.popupNode;
|
||||||
|
if (!node.classList.contains("property-view")) {
|
||||||
|
while (node = node.parentElement) {
|
||||||
|
if (node.classList.contains("property-view")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let disablePropertyItems = !node;
|
||||||
|
menuitem = this.doc.querySelector("#computed-view-copy-declaration");
|
||||||
|
menuitem.disabled = disablePropertyItems;
|
||||||
|
menuitem = this.doc.querySelector("#computed-view-copy-property");
|
||||||
|
menuitem.disabled = disablePropertyItems;
|
||||||
|
menuitem = this.doc.querySelector("#computed-view-copy-property-value");
|
||||||
|
menuitem.disabled = disablePropertyItems;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy selected text.
|
||||||
|
*
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
computedViewCopy: function si_computedViewCopy(aEvent)
|
||||||
|
{
|
||||||
|
let win = this.styleDocument.defaultView;
|
||||||
|
let text = win.getSelection().toString();
|
||||||
|
|
||||||
|
// Tidy up block headings by moving CSS property names and their values onto
|
||||||
|
// the same line and inserting a colon between them.
|
||||||
|
text = text.replace(/(.+)\r?\n\s+/g, "$1: ");
|
||||||
|
|
||||||
|
// Remove any MDN link titles
|
||||||
|
text = text.replace(CssHtmlTree.HELP_LINK_TITLE, "");
|
||||||
|
clipboardHelper.copyString(text);
|
||||||
|
|
||||||
|
if (aEvent) {
|
||||||
|
aEvent.preventDefault();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy declaration.
|
||||||
|
*
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
computedViewCopyDeclaration: function si_computedViewCopyDeclaration(aEvent)
|
||||||
|
{
|
||||||
|
let node = this.doc.popupNode;
|
||||||
|
if (!node.classList.contains("property-view")) {
|
||||||
|
while (node = node.parentElement) {
|
||||||
|
if (node.classList.contains("property-view")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node) {
|
||||||
|
let name = node.querySelector(".property-name").textContent;
|
||||||
|
let value = node.querySelector(".property-value").textContent;
|
||||||
|
|
||||||
|
clipboardHelper.copyString(name + ": " + value + ";");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy property name.
|
||||||
|
*
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
computedViewCopyProperty: function si_computedViewCopyProperty(aEvent)
|
||||||
|
{
|
||||||
|
let node = this.doc.popupNode;
|
||||||
|
if (!node.classList.contains("property-view")) {
|
||||||
|
while (node = node.parentElement) {
|
||||||
|
if (node.classList.contains("property-view")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node) {
|
||||||
|
node = node.querySelector(".property-name");
|
||||||
|
clipboardHelper.copyString(node.textContent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy property value.
|
||||||
|
*
|
||||||
|
* @param aEvent The event object
|
||||||
|
*/
|
||||||
|
computedViewCopyPropertyValue: function si_computedViewCopyPropertyValue(aEvent)
|
||||||
|
{
|
||||||
|
let node = this.doc.popupNode;
|
||||||
|
if (!node.classList.contains("property-view")) {
|
||||||
|
while (node = node.parentElement) {
|
||||||
|
if (node.classList.contains("property-view")) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node) {
|
||||||
|
node = node.querySelector(".property-value");
|
||||||
|
clipboardHelper.copyString(node.textContent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor for CssHtmlTree.
|
* Destructor for CssHtmlTree.
|
||||||
*/
|
*/
|
||||||
@@ -486,6 +673,32 @@ CssHtmlTree.prototype = {
|
|||||||
this._refreshProcess.cancel();
|
this._refreshProcess.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove context menu
|
||||||
|
let menu = this.doc.querySelector("#computed-view-context-menu");
|
||||||
|
if (menu) {
|
||||||
|
// Copy selected
|
||||||
|
let menuitem = this.doc.querySelector("#computed-view-copy");
|
||||||
|
menuitem.removeEventListener("command", this.siBoundCopy);
|
||||||
|
|
||||||
|
// Copy property
|
||||||
|
menuitem = this.doc.querySelector("#computed-view-copy-declaration");
|
||||||
|
menuitem.removeEventListener("command", this.siBoundCopyDeclaration);
|
||||||
|
|
||||||
|
// Copy property name
|
||||||
|
menuitem = this.doc.querySelector("#computed-view-copy-property");
|
||||||
|
menuitem.removeEventListener("command", this.siBoundCopyProperty);
|
||||||
|
|
||||||
|
// Copy property value
|
||||||
|
menuitem = this.doc.querySelector("#computed-view-copy-property-value");
|
||||||
|
menuitem.removeEventListener("command", this.siBoundCopyPropertyValue);
|
||||||
|
|
||||||
|
menu.removeEventListener("popupshowing", this.siBoundMenuUpdate);
|
||||||
|
menu.parentNode.removeChild(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove bound listeners
|
||||||
|
this.styleDocument.removeEventListener("copy", this.siBoundCopy);
|
||||||
|
|
||||||
// Nodes used in templating
|
// Nodes used in templating
|
||||||
delete this.root;
|
delete this.root;
|
||||||
delete this.propertyContainer;
|
delete this.propertyContainer;
|
||||||
@@ -658,32 +871,35 @@ PropertyView.prototype = {
|
|||||||
let doc = this.tree.doc;
|
let doc = this.tree.doc;
|
||||||
this.element = doc.createElementNS(HTML_NS, "tr");
|
this.element = doc.createElementNS(HTML_NS, "tr");
|
||||||
this.element.setAttribute("class", this.propertyHeaderClassName);
|
this.element.setAttribute("class", this.propertyHeaderClassName);
|
||||||
this.element.addEventListener("click", this.propertyRowClick.bind(this), false);
|
|
||||||
|
|
||||||
this.propertyHeader = doc.createElementNS(HTML_NS, "td");
|
this.propertyHeader = doc.createElementNS(HTML_NS, "td");
|
||||||
this.element.appendChild(this.propertyHeader);
|
this.element.appendChild(this.propertyHeader);
|
||||||
this.propertyHeader.setAttribute("class", "property-header");
|
this.propertyHeader.setAttribute("class", "property-header");
|
||||||
|
|
||||||
this.matchedExpander = doc.createElementNS(HTML_NS, "div");
|
this.matchedExpander = doc.createElementNS(HTML_NS, "div");
|
||||||
this.propertyHeader.appendChild(this.matchedExpander);
|
|
||||||
this.matchedExpander.setAttribute("class", "match expander");
|
this.matchedExpander.setAttribute("class", "match expander");
|
||||||
|
this.matchedExpander.setAttribute("tabindex", "0");
|
||||||
this.nameNode = doc.createElementNS(HTML_NS, "div");
|
this.matchedExpander.addEventListener("click",
|
||||||
this.propertyHeader.appendChild(this.nameNode);
|
this.matchedExpanderClick.bind(this), false);
|
||||||
this.nameNode.setAttribute("tabindex", "0");
|
this.matchedExpander.addEventListener("keydown", function(aEvent) {
|
||||||
this.nameNode.addEventListener("keydown", function(aEvent) {
|
|
||||||
let keyEvent = Ci.nsIDOMKeyEvent;
|
let keyEvent = Ci.nsIDOMKeyEvent;
|
||||||
if (aEvent.keyCode == keyEvent.DOM_VK_F1) {
|
if (aEvent.keyCode == keyEvent.DOM_VK_F1) {
|
||||||
this.mdnLinkClick();
|
this.mdnLinkClick();
|
||||||
}
|
}
|
||||||
if (aEvent.keyCode == keyEvent.DOM_VK_RETURN ||
|
if (aEvent.keyCode == keyEvent.DOM_VK_RETURN ||
|
||||||
aEvent.keyCode == keyEvent.DOM_VK_SPACE) {
|
aEvent.keyCode == keyEvent.DOM_VK_SPACE) {
|
||||||
this.propertyRowClick(aEvent);
|
this.matchedExpanderClick(aEvent);
|
||||||
}
|
}
|
||||||
}.bind(this), false);
|
}.bind(this), false);
|
||||||
|
this.propertyHeader.appendChild(this.matchedExpander);
|
||||||
|
|
||||||
|
this.nameNode = doc.createElementNS(HTML_NS, "div");
|
||||||
|
this.propertyHeader.appendChild(this.nameNode);
|
||||||
this.nameNode.setAttribute("class", "property-name");
|
this.nameNode.setAttribute("class", "property-name");
|
||||||
this.nameNode.textContent = this.name;
|
this.nameNode.textContent = this.name;
|
||||||
|
this.nameNode.addEventListener("click", function(aEvent) {
|
||||||
|
this.matchedExpander.focus();
|
||||||
|
}.bind(this), false);
|
||||||
|
|
||||||
let helpcontainer = doc.createElementNS(HTML_NS, "td");
|
let helpcontainer = doc.createElementNS(HTML_NS, "td");
|
||||||
this.element.appendChild(helpcontainer);
|
this.element.appendChild(helpcontainer);
|
||||||
@@ -754,9 +970,9 @@ PropertyView.prototype = {
|
|||||||
this.matchedSelectorsContainer.parentNode.hidden = !hasMatchedSelectors;
|
this.matchedSelectorsContainer.parentNode.hidden = !hasMatchedSelectors;
|
||||||
|
|
||||||
if (hasMatchedSelectors) {
|
if (hasMatchedSelectors) {
|
||||||
this.propertyHeader.parentNode.classList.add("expandable");
|
this.matchedExpander.classList.add("expandable");
|
||||||
} else {
|
} else {
|
||||||
this.propertyHeader.parentNode.classList.remove("expandable");
|
this.matchedExpander.classList.remove("expandable");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.matchedExpanded && hasMatchedSelectors) {
|
if (this.matchedExpanded && hasMatchedSelectors) {
|
||||||
@@ -852,17 +1068,13 @@ PropertyView.prototype = {
|
|||||||
* The action when a user expands matched selectors.
|
* The action when a user expands matched selectors.
|
||||||
*
|
*
|
||||||
* @param {Event} aEvent Used to determine the class name of the targets click
|
* @param {Event} aEvent Used to determine the class name of the targets click
|
||||||
* event. If the class name is "helplink" then the event is allowed to bubble
|
* event.
|
||||||
* to the mdn link icon.
|
|
||||||
*/
|
*/
|
||||||
propertyRowClick: function PropertyView_propertyRowClick(aEvent)
|
matchedExpanderClick: function PropertyView_matchedExpanderClick(aEvent)
|
||||||
{
|
{
|
||||||
if (aEvent.target.className != "helplink") {
|
this.matchedExpanded = !this.matchedExpanded;
|
||||||
this.matchedExpanded = !this.matchedExpanded;
|
this.refreshAllSelectors();
|
||||||
this.refreshAllSelectors();
|
aEvent.preventDefault();
|
||||||
this.nameNode.focus();
|
|
||||||
aEvent.preventDefault();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -986,6 +1198,14 @@ SelectorView.prototype = {
|
|||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
maybeOpenStyleEditor: function(aEvent)
|
||||||
|
{
|
||||||
|
let keyEvent = Ci.nsIDOMKeyEvent;
|
||||||
|
if (aEvent.keyCode == keyEvent.DOM_VK_RETURN) {
|
||||||
|
this.openStyleEditor();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a css link is clicked this method is called in order to either:
|
* When a css link is clicked this method is called in order to either:
|
||||||
* 1. Open the link in view source (for element style attributes).
|
* 1. Open the link in view source (for element style attributes).
|
||||||
|
|||||||
@@ -927,7 +927,8 @@ CssLogic.shortSource = function CssLogic_shortSource(aSheet)
|
|||||||
return url.query;
|
return url.query;
|
||||||
}
|
}
|
||||||
|
|
||||||
return aSheet.href;
|
let dataUrl = aSheet.href.match(/^(data:[^,]*),/);
|
||||||
|
return dataUrl ? dataUrl[1] : aSheet.href;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Dave Camp <dcamp@mozilla.com> (Original Author)
|
* Dave Camp <dcamp@mozilla.com> (Original Author)
|
||||||
* Rob Campbell <rcampbell@mozilla.com>
|
* Rob Campbell <rcampbell@mozilla.com>
|
||||||
|
* Mike Ratcliffe <mratcliffe@mozilla.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
@@ -807,7 +808,7 @@ CssRuleView.prototype = {
|
|||||||
for each (let rule in this._elementStyle.rules) {
|
for each (let rule in this._elementStyle.rules) {
|
||||||
// Don't hold a reference to this editor beyond the one held
|
// Don't hold a reference to this editor beyond the one held
|
||||||
// by the node.
|
// by the node.
|
||||||
let editor = new RuleEditor(this.doc, rule);
|
let editor = new RuleEditor(this, rule);
|
||||||
this.element.appendChild(editor.element);
|
this.element.appendChild(editor.element);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -816,15 +817,17 @@ CssRuleView.prototype = {
|
|||||||
/**
|
/**
|
||||||
* Create a RuleEditor.
|
* Create a RuleEditor.
|
||||||
*
|
*
|
||||||
* @param object aDoc
|
* @param CssRuleView aRuleView
|
||||||
* The document holding this rule editor.
|
* The CssRuleView containg the document holding this rule editor and the
|
||||||
|
* _selectionMode flag.
|
||||||
* @param Rule aRule
|
* @param Rule aRule
|
||||||
* The Rule object we're editing.
|
* The Rule object we're editing.
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function RuleEditor(aDoc, aRule)
|
function RuleEditor(aRuleView, aRule)
|
||||||
{
|
{
|
||||||
this.doc = aDoc;
|
this.ruleView = aRuleView;
|
||||||
|
this.doc = this.ruleView.doc;
|
||||||
this.rule = aRule;
|
this.rule = aRule;
|
||||||
|
|
||||||
this._onNewProperty = this._onNewProperty.bind(this);
|
this._onNewProperty = this._onNewProperty.bind(this);
|
||||||
@@ -893,8 +896,16 @@ RuleEditor.prototype = {
|
|||||||
|
|
||||||
// We made the close brace focusable, tabbing to it
|
// We made the close brace focusable, tabbing to it
|
||||||
// or clicking on it should start the new property editor.
|
// or clicking on it should start the new property editor.
|
||||||
this.closeBrace.addEventListener("focus", function() {
|
this.closeBrace.addEventListener("focus", function(aEvent) {
|
||||||
this.newProperty();
|
if (!this.ruleView._selectionMode) {
|
||||||
|
this.newProperty();
|
||||||
|
}
|
||||||
|
}.bind(this), true);
|
||||||
|
this.closeBrace.addEventListener("mousedown", function(aEvent) {
|
||||||
|
aEvent.preventDefault();
|
||||||
|
}.bind(this), true);
|
||||||
|
this.closeBrace.addEventListener("click", function(aEvent) {
|
||||||
|
this.closeBrace.focus();
|
||||||
}.bind(this), true);
|
}.bind(this), true);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1261,6 +1272,21 @@ function editableField(aOptions)
|
|||||||
aOptions.element.addEventListener("focus", function() {
|
aOptions.element.addEventListener("focus", function() {
|
||||||
new InplaceEditor(aOptions);
|
new InplaceEditor(aOptions);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
|
// In order to allow selection on the element, prevent focus on
|
||||||
|
// mousedown. Focus on click instead.
|
||||||
|
aOptions.element.addEventListener("mousedown", function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
}, false);
|
||||||
|
aOptions.element.addEventListener("click", function(evt) {
|
||||||
|
let win = this.ownerDocument.defaultView;
|
||||||
|
let selection = win.getSelection();
|
||||||
|
if (selection.isCollapsed) {
|
||||||
|
aOptions.element.focus();
|
||||||
|
} else {
|
||||||
|
selection.removeAllRanges();
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
}
|
}
|
||||||
var _editableField = editableField;
|
var _editableField = editableField;
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ var EXPORTED_SYMBOLS = ["StyleInspector"];
|
|||||||
function StyleInspector(aContext, aIUI)
|
function StyleInspector(aContext, aIUI)
|
||||||
{
|
{
|
||||||
this._init(aContext, aIUI);
|
this._init(aContext, aIUI);
|
||||||
};
|
}
|
||||||
|
|
||||||
StyleInspector.prototype = {
|
StyleInspector.prototype = {
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
- ***** END LICENSE BLOCK ***** -->
|
- ***** END LICENSE BLOCK ***** -->
|
||||||
|
|
||||||
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
||||||
|
<?xml-stylesheet href="chrome://browser/content/devtools/styleinspector.css" type="text/css"?>
|
||||||
<?xml-stylesheet href="chrome://browser/skin/devtools/csshtmltree.css" type="text/css"?>
|
<?xml-stylesheet href="chrome://browser/skin/devtools/csshtmltree.css" type="text/css"?>
|
||||||
|
|
||||||
<!DOCTYPE window [
|
<!DOCTYPE window [
|
||||||
@@ -114,8 +115,11 @@ To visually debug the templates without running firefox, alter the display:none
|
|||||||
${selector.humanReadableText(__element)}
|
${selector.humanReadableText(__element)}
|
||||||
</td>
|
</td>
|
||||||
<td class="rule-link">
|
<td class="rule-link">
|
||||||
<a target="_blank" onclick="${selector.openStyleEditor}" class="link"
|
<a target="_blank" class="link"
|
||||||
title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
|
onclick="${selector.openStyleEditor}"
|
||||||
|
onkeydown="${selector.maybeOpenStyleEditor}"
|
||||||
|
title="${selector.selectorInfo.href}"
|
||||||
|
tabindex="0">${selector.selectorInfo.source}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</loop>
|
</loop>
|
||||||
|
|||||||
@@ -35,11 +35,39 @@
|
|||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
.ruleview {
|
#root {
|
||||||
overflow: auto;
|
display: -moz-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ruleview-computedlist:not(.styleinspector-open) {
|
.helplink {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expander,
|
||||||
|
.property-name,
|
||||||
|
.ruleview-propertyname,
|
||||||
|
.ruleview-warning,
|
||||||
|
.ruleview-expander {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#propertyContainer {
|
||||||
|
display: -moz-box;
|
||||||
|
-moz-box-orient: vertical;
|
||||||
|
-moz-box-flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
-moz-user-select: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruleview {
|
||||||
|
overflow: auto;
|
||||||
|
-moz-user-select: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.property-view-hidden,
|
||||||
|
.property-content-hidden,
|
||||||
|
.ruleview-computedlist:not(.styleinspector-open),
|
||||||
|
.ruleview-warning[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ _BROWSER_TEST_FILES = \
|
|||||||
browser_bug722196_property_view_media_queries.js \
|
browser_bug722196_property_view_media_queries.js \
|
||||||
browser_bug722196_rule_view_media_queries.js \
|
browser_bug722196_rule_view_media_queries.js \
|
||||||
browser_bug_592743_specificity.js \
|
browser_bug_592743_specificity.js \
|
||||||
|
browser_ruleview_bug_703643_context_menu_copy.js \
|
||||||
|
browser_computedview_bug_703643_context_menu_copy.js \
|
||||||
head.js \
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|||||||
@@ -55,12 +55,12 @@ function SI_test()
|
|||||||
let searchbar = stylePanel.cssHtmlTree.searchField;
|
let searchbar = stylePanel.cssHtmlTree.searchField;
|
||||||
let propView = getFirstVisiblePropertyView();
|
let propView = getFirstVisiblePropertyView();
|
||||||
let rulesTable = propView.matchedSelectorsContainer;
|
let rulesTable = propView.matchedSelectorsContainer;
|
||||||
let nameNode = propView.nameNode;
|
let matchedExpander = propView.matchedExpander;
|
||||||
|
|
||||||
info("Adding focus event handler to property name node");
|
info("Adding focus event handler to property expander");
|
||||||
nameNode.addEventListener("focus", function nameFocused() {
|
matchedExpander.addEventListener("focus", function expanderFocused() {
|
||||||
this.removeEventListener("focus", nameFocused);
|
this.removeEventListener("focus", expanderFocused);
|
||||||
info("property name is focused");
|
info("property expander is focused");
|
||||||
info("checking expand / collapse");
|
info("checking expand / collapse");
|
||||||
testKey(iframe.contentWindow, "VK_SPACE", rulesTable);
|
testKey(iframe.contentWindow, "VK_SPACE", rulesTable);
|
||||||
testKey(iframe.contentWindow, "VK_RETURN", rulesTable);
|
testKey(iframe.contentWindow, "VK_RETURN", rulesTable);
|
||||||
@@ -74,7 +74,7 @@ function SI_test()
|
|||||||
searchbar.addEventListener("focus", function searchbarFocused() {
|
searchbar.addEventListener("focus", function searchbarFocused() {
|
||||||
this.removeEventListener("focus", searchbarFocused);
|
this.removeEventListener("focus", searchbarFocused);
|
||||||
info("search filter is focused");
|
info("search filter is focused");
|
||||||
info("tabbing to property name node");
|
info("tabbing to property expander node");
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, iframe.contentWindow);
|
EventUtils.synthesizeKey("VK_TAB", {}, iframe.contentWindow);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
// Tests that the style inspector works properly
|
||||||
|
|
||||||
|
let doc;
|
||||||
|
let stylePanel;
|
||||||
|
let cssHtmlTree;
|
||||||
|
|
||||||
|
function createDocument()
|
||||||
|
{
|
||||||
|
doc.body.innerHTML = '<style type="text/css"> ' +
|
||||||
|
'span { font-variant: small-caps; color: #000000; } ' +
|
||||||
|
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
|
||||||
|
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
|
||||||
|
'<h1>Some header text</h1>\n' +
|
||||||
|
'<p id="salutation" style="font-size: 12pt">hi.</p>\n' +
|
||||||
|
'<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' +
|
||||||
|
'solely to provide some things to <span style="color: yellow">' +
|
||||||
|
'highlight</span> and <span style="font-weight: bold">count</span> ' +
|
||||||
|
'style list-items in the box at right. If you are reading this, ' +
|
||||||
|
'you should go do something else instead. Maybe read a book. Or better ' +
|
||||||
|
'yet, write some test-cases for another bit of code. ' +
|
||||||
|
'<span style="font-style: italic">some text</span></p>\n' +
|
||||||
|
'<p id="closing">more text</p>\n' +
|
||||||
|
'<p>even more text</p>' +
|
||||||
|
'</div>';
|
||||||
|
doc.title = "Computed view context menu test";
|
||||||
|
|
||||||
|
let span = doc.querySelector("span");
|
||||||
|
ok(span, "captain, we have the span");
|
||||||
|
|
||||||
|
stylePanel = new StyleInspector(window);
|
||||||
|
Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-populated", false);
|
||||||
|
stylePanel.createPanel(false, function() {
|
||||||
|
stylePanel.open(span);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function runStyleInspectorTests()
|
||||||
|
{
|
||||||
|
Services.obs.removeObserver(runStyleInspectorTests, "StyleInspector-populated", false);
|
||||||
|
|
||||||
|
ok(stylePanel.isOpen(), "style inspector is open");
|
||||||
|
|
||||||
|
cssHtmlTree = stylePanel.cssHtmlTree;
|
||||||
|
|
||||||
|
let contentDocument = stylePanel.iframe.contentDocument;
|
||||||
|
let prop = contentDocument.querySelector(".property-view");
|
||||||
|
ok(prop, "captain, we have the property-view node");
|
||||||
|
|
||||||
|
// We need the context menu to open in the correct place in order for
|
||||||
|
// popupNode to be propertly set.
|
||||||
|
EventUtils.synthesizeMouse(prop, 1, 1, { type: "contextmenu", button: 2 },
|
||||||
|
stylePanel.iframe.contentWindow);
|
||||||
|
|
||||||
|
checkCopyProperty()
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCopyProperty()
|
||||||
|
{
|
||||||
|
info("Checking that cssHtmlTree.siBoundCopyDeclaration() returns the " +
|
||||||
|
"correct clipboard value");
|
||||||
|
let expectedPattern = "color: rgb\\(255, 255, 0\\);";
|
||||||
|
info("Expected pattern: " + expectedPattern);
|
||||||
|
|
||||||
|
SimpleTest.waitForClipboard(function CS_boundCopyPropCheck() {
|
||||||
|
return checkClipboardData(expectedPattern);
|
||||||
|
},
|
||||||
|
cssHtmlTree.siBoundCopyDeclaration,
|
||||||
|
checkCopyPropertyName, checkCopyPropertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCopyPropertyName()
|
||||||
|
{
|
||||||
|
info("Checking that cssHtmlTree.siBoundCopyProperty() returns the " +
|
||||||
|
"correct clipboard value");
|
||||||
|
let expectedPattern = "color";
|
||||||
|
info("Expected pattern: " + expectedPattern);
|
||||||
|
|
||||||
|
SimpleTest.waitForClipboard(function CS_boundCopyPropNameCheck() {
|
||||||
|
return checkClipboardData(expectedPattern);
|
||||||
|
},
|
||||||
|
cssHtmlTree.siBoundCopyProperty,
|
||||||
|
checkCopyPropertyValue, checkCopyPropertyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCopyPropertyValue()
|
||||||
|
{
|
||||||
|
info("Checking that cssHtmlTree.siBoundCopyPropertyValue() returns the " +
|
||||||
|
"correct clipboard value");
|
||||||
|
let expectedPattern = "rgb\\(255, 255, 0\\)";
|
||||||
|
info("Expected pattern: " + expectedPattern);
|
||||||
|
|
||||||
|
SimpleTest.waitForClipboard(function CS_boundCopyPropValueCheck() {
|
||||||
|
return checkClipboardData(expectedPattern);
|
||||||
|
},
|
||||||
|
cssHtmlTree.siBoundCopyPropertyValue,
|
||||||
|
checkCopySelection, checkCopySelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCopySelection()
|
||||||
|
{
|
||||||
|
let contentDocument = stylePanel.iframe.contentDocument;
|
||||||
|
let contentWindow = stylePanel.iframe.contentWindow;
|
||||||
|
let props = contentDocument.querySelectorAll(".property-view");
|
||||||
|
ok(props, "captain, we have the property-view nodes");
|
||||||
|
|
||||||
|
let range = document.createRange();
|
||||||
|
range.setStart(props[0], 0);
|
||||||
|
range.setEnd(props[3], 3);
|
||||||
|
contentWindow.getSelection().addRange(range);
|
||||||
|
|
||||||
|
info("Checking that cssHtmlTree.siBoundCopyPropertyValue() " +
|
||||||
|
" returns the correct clipboard value");
|
||||||
|
|
||||||
|
let expectedPattern = "color: rgb\\(255, 255, 0\\)[\\r\\n]+" +
|
||||||
|
"font-family: helvetica,sans-serif[\\r\\n]+" +
|
||||||
|
"font-size: 16px[\\r\\n]+" +
|
||||||
|
"font-variant: small-caps[\\r\\n]*";
|
||||||
|
info("Expected pattern: " + expectedPattern);
|
||||||
|
|
||||||
|
SimpleTest.waitForClipboard(function CS_boundCopyCheck() {
|
||||||
|
return checkClipboardData(expectedPattern);
|
||||||
|
},
|
||||||
|
cssHtmlTree.siBoundCopy, closeStyleInspector, closeStyleInspector);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkClipboardData(aExpectedPattern)
|
||||||
|
{
|
||||||
|
let actual = SpecialPowers.getClipboardData("text/unicode");
|
||||||
|
let expectedRegExp = new RegExp(aExpectedPattern, "g");
|
||||||
|
return expectedRegExp.test(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeStyleInspector()
|
||||||
|
{
|
||||||
|
Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
|
||||||
|
stylePanel.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishUp()
|
||||||
|
{
|
||||||
|
Services.obs.removeObserver(finishUp, "StyleInspector-closed", false);
|
||||||
|
ok(!stylePanel.isOpen(), "style inspector is closed");
|
||||||
|
doc = stylePanel = cssHtmlTree = null;
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
waitForExplicitFinish();
|
||||||
|
gBrowser.selectedTab = gBrowser.addTab();
|
||||||
|
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
|
||||||
|
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
|
||||||
|
doc = content.document;
|
||||||
|
waitForFocus(createDocument, content);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
content.location = "data:text/html,computed view context menu test";
|
||||||
|
}
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
let doc;
|
||||||
|
|
||||||
|
function createDocument()
|
||||||
|
{
|
||||||
|
doc.body.innerHTML = '<style type="text/css"> ' +
|
||||||
|
'html { color: #000000; } ' +
|
||||||
|
'span { font-variant: small-caps; color: #000000; } ' +
|
||||||
|
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
|
||||||
|
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
|
||||||
|
'<h1>Some header text</h1>\n' +
|
||||||
|
'<p id="salutation" style="font-size: 12pt">hi.</p>\n' +
|
||||||
|
'<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' +
|
||||||
|
'solely to provide some things to <span style="color: yellow">' +
|
||||||
|
'highlight</span> and <span style="font-weight: bold">count</span> ' +
|
||||||
|
'style list-items in the box at right. If you are reading this, ' +
|
||||||
|
'you should go do something else instead. Maybe read a book. Or better ' +
|
||||||
|
'yet, write some test-cases for another bit of code. ' +
|
||||||
|
'<span style="font-style: italic">some text</span></p>\n' +
|
||||||
|
'<p id="closing">more text</p>\n' +
|
||||||
|
'<p>even more text</p>' +
|
||||||
|
'</div>';
|
||||||
|
doc.title = "Rule view context menu test";
|
||||||
|
|
||||||
|
openInspector();
|
||||||
|
}
|
||||||
|
|
||||||
|
function openInspector()
|
||||||
|
{
|
||||||
|
ok(window.InspectorUI, "InspectorUI variable exists");
|
||||||
|
ok(!InspectorUI.inspecting, "Inspector is not highlighting");
|
||||||
|
ok(InspectorUI.store.isEmpty(), "Inspector.store is empty");
|
||||||
|
|
||||||
|
Services.obs.addObserver(inspectorUIOpen,
|
||||||
|
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||||
|
InspectorUI.openInspectorUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
function inspectorUIOpen()
|
||||||
|
{
|
||||||
|
Services.obs.removeObserver(inspectorUIOpen,
|
||||||
|
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||||
|
|
||||||
|
// Make sure the inspector is open.
|
||||||
|
ok(InspectorUI.inspecting, "Inspector is highlighting");
|
||||||
|
ok(!InspectorUI.treePanel.isOpen(), "Inspector Tree Panel is not open");
|
||||||
|
ok(!InspectorUI.isSidebarOpen, "Inspector Sidebar is not open");
|
||||||
|
ok(!InspectorUI.store.isEmpty(), "InspectorUI.store is not empty");
|
||||||
|
is(InspectorUI.store.length, 1, "Inspector.store.length = 1");
|
||||||
|
|
||||||
|
// Highlight a node.
|
||||||
|
let div = content.document.getElementsByTagName("div")[0];
|
||||||
|
InspectorUI.inspectNode(div);
|
||||||
|
InspectorUI.stopInspecting();
|
||||||
|
is(InspectorUI.selection, div, "selection matches the div element");
|
||||||
|
|
||||||
|
Services.obs.addObserver(testClip,
|
||||||
|
InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, false);
|
||||||
|
|
||||||
|
InspectorUI.showSidebar();
|
||||||
|
InspectorUI.openRuleView();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testClip()
|
||||||
|
{
|
||||||
|
Services.obs.removeObserver(testClip,
|
||||||
|
InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, false);
|
||||||
|
|
||||||
|
executeSoon(function() {
|
||||||
|
info("Checking that InspectorUI.ruleViewCopyRule() returns " +
|
||||||
|
"the correct clipboard value");
|
||||||
|
let expectedPattern = "element {[\\r\\n]+" +
|
||||||
|
" margin: 10em;[\\r\\n]+" +
|
||||||
|
" font-size: 14pt;[\\r\\n]+" +
|
||||||
|
" font-family: helvetica,sans-serif;[\\r\\n]+" +
|
||||||
|
" color: rgb\\(170, 170, 170\\);[\\r\\n]+" +
|
||||||
|
"}[\\r\\n]*";
|
||||||
|
info("Expected pattern: " + expectedPattern);
|
||||||
|
|
||||||
|
SimpleTest.waitForClipboard(function IUI_boundCopyPropCheck() {
|
||||||
|
return checkClipboardData(expectedPattern);
|
||||||
|
},
|
||||||
|
checkCopyRule, checkCopyProperty, checkCopyProperty);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCopyRule() {
|
||||||
|
let ruleView = document.querySelector("#devtools-sidebar-iframe-ruleview");
|
||||||
|
let contentDoc = ruleView.contentDocument;
|
||||||
|
let props = contentDoc.querySelectorAll(".ruleview-property");
|
||||||
|
|
||||||
|
is(props.length, 5, "checking property length");
|
||||||
|
|
||||||
|
let prop = props[2];
|
||||||
|
let propName = prop.querySelector(".ruleview-propertyname").textContent;
|
||||||
|
let propValue = prop.querySelector(".ruleview-propertyvalue").textContent;
|
||||||
|
|
||||||
|
is(propName, "font-family", "checking property name");
|
||||||
|
is(propValue, "helvetica,sans-serif", "checking property value");
|
||||||
|
|
||||||
|
// We need the context menu to open in the correct place in order for
|
||||||
|
// popupNode to be propertly set.
|
||||||
|
EventUtils.synthesizeMouse(prop, 1, 1, { type: "contextmenu", button: 2 },
|
||||||
|
ruleView.contentWindow);
|
||||||
|
|
||||||
|
InspectorUI.ruleViewCopyRule();
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCopyProperty()
|
||||||
|
{
|
||||||
|
info("Checking that InspectorUI.cssRuleViewBoundCopyDeclaration() returns " +
|
||||||
|
"the correct clipboard value");
|
||||||
|
let expectedPattern = "font-family: helvetica,sans-serif;";
|
||||||
|
info("Expected pattern: " + expectedPattern);
|
||||||
|
|
||||||
|
SimpleTest.waitForClipboard(function IUI_boundCopyPropCheck() {
|
||||||
|
return checkClipboardData(expectedPattern);
|
||||||
|
},
|
||||||
|
InspectorUI.cssRuleViewBoundCopyDeclaration,
|
||||||
|
checkCopyPropertyName, checkCopyPropertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCopyPropertyName()
|
||||||
|
{
|
||||||
|
info("Checking that InspectorUI.cssRuleViewBoundCopyProperty() returns " +
|
||||||
|
"the correct clipboard value");
|
||||||
|
let expectedPattern = "font-family";
|
||||||
|
info("Expected pattern: " + expectedPattern);
|
||||||
|
|
||||||
|
SimpleTest.waitForClipboard(function IUI_boundCopyPropNameCheck() {
|
||||||
|
return checkClipboardData(expectedPattern);
|
||||||
|
},
|
||||||
|
InspectorUI.cssRuleViewBoundCopyProperty,
|
||||||
|
checkCopyPropertyValue, checkCopyPropertyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCopyPropertyValue()
|
||||||
|
{
|
||||||
|
info("Checking that InspectorUI.cssRuleViewBoundCopyPropertyValue() " +
|
||||||
|
" returns the correct clipboard value");
|
||||||
|
let expectedPattern = "helvetica,sans-serif";
|
||||||
|
info("Expected pattern: " + expectedPattern);
|
||||||
|
|
||||||
|
SimpleTest.waitForClipboard(function IUI_boundCopyPropValueCheck() {
|
||||||
|
return checkClipboardData(expectedPattern);
|
||||||
|
},
|
||||||
|
InspectorUI.cssRuleViewBoundCopyPropertyValue,
|
||||||
|
checkCopySelection, checkCopySelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCopySelection()
|
||||||
|
{
|
||||||
|
let ruleView = document.querySelector("#devtools-sidebar-iframe-ruleview");
|
||||||
|
let contentDoc = ruleView.contentDocument;
|
||||||
|
let props = contentDoc.querySelectorAll(".ruleview-property");
|
||||||
|
|
||||||
|
let range = document.createRange();
|
||||||
|
range.setStart(props[0], 0);
|
||||||
|
range.setEnd(props[4], 8);
|
||||||
|
ruleView.contentWindow.getSelection().addRange(range);
|
||||||
|
|
||||||
|
info("Checking that InspectorUI.cssRuleViewBoundCopy() returns the correct" +
|
||||||
|
"clipboard value");
|
||||||
|
let expectedPattern = " margin: 10em;[\\r\\n]+" +
|
||||||
|
" font-size: 14pt;[\\r\\n]+" +
|
||||||
|
" font-family: helvetica,sans-serif;[\\r\\n]+" +
|
||||||
|
" color: rgb\\(170, 170, 170\\);[\\r\\n]+" +
|
||||||
|
"}[\\r\\n]+" +
|
||||||
|
"html {[\\r\\n]+" +
|
||||||
|
" color: rgb\\(0, 0, 0\\);[\\r\\n]*";
|
||||||
|
info("Expected pattern: " + expectedPattern);
|
||||||
|
|
||||||
|
SimpleTest.waitForClipboard(function IUI_boundCopyCheck() {
|
||||||
|
return checkClipboardData(expectedPattern);
|
||||||
|
},InspectorUI.cssRuleViewBoundCopy, finishup, finishup);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkClipboardData(aExpectedPattern)
|
||||||
|
{
|
||||||
|
let actual = SpecialPowers.getClipboardData("text/unicode");
|
||||||
|
let expectedRegExp = new RegExp(aExpectedPattern, "g");
|
||||||
|
return expectedRegExp.test(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishup()
|
||||||
|
{
|
||||||
|
InspectorUI.closeInspectorUI();
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
doc = null;
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
gBrowser.selectedTab = gBrowser.addTab();
|
||||||
|
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
|
||||||
|
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee,
|
||||||
|
true);
|
||||||
|
doc = content.document;
|
||||||
|
waitForFocus(createDocument, content);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
content.location = "data:text/html,<p>rule view context menu test</p>";
|
||||||
|
}
|
||||||
@@ -144,6 +144,7 @@
|
|||||||
@BINPATH@/components/directory.xpt
|
@BINPATH@/components/directory.xpt
|
||||||
@BINPATH@/components/docshell.xpt
|
@BINPATH@/components/docshell.xpt
|
||||||
@BINPATH@/components/dom.xpt
|
@BINPATH@/components/dom.xpt
|
||||||
|
@BINPATH@/components/dom_apps.xpt
|
||||||
@BINPATH@/components/dom_base.xpt
|
@BINPATH@/components/dom_base.xpt
|
||||||
#ifdef MOZ_B2G_RIL
|
#ifdef MOZ_B2G_RIL
|
||||||
@BINPATH@/components/dom_telephony.xpt
|
@BINPATH@/components/dom_telephony.xpt
|
||||||
@@ -410,6 +411,8 @@
|
|||||||
@BINPATH@/components/TelemetryPing.manifest
|
@BINPATH@/components/TelemetryPing.manifest
|
||||||
@BINPATH@/components/messageWakeupService.js
|
@BINPATH@/components/messageWakeupService.js
|
||||||
@BINPATH@/components/messageWakeupService.manifest
|
@BINPATH@/components/messageWakeupService.manifest
|
||||||
|
@BINPATH@/components/Webapps.js
|
||||||
|
@BINPATH@/components/Webapps.manifest
|
||||||
|
|
||||||
@BINPATH@/components/ContactManager.js
|
@BINPATH@/components/ContactManager.js
|
||||||
@BINPATH@/components/ContactManager.manifest
|
@BINPATH@/components/ContactManager.manifest
|
||||||
|
|||||||
@@ -213,8 +213,6 @@ can reach it easily. -->
|
|||||||
<!ENTITY scratchpad.keycode "VK_F4">
|
<!ENTITY scratchpad.keycode "VK_F4">
|
||||||
<!ENTITY scratchpad.keytext "F4">
|
<!ENTITY scratchpad.keytext "F4">
|
||||||
|
|
||||||
<!ENTITY inspectButton.label "Inspect">
|
|
||||||
<!ENTITY inspectButton.accesskey "I">
|
|
||||||
<!ENTITY inspectCloseButton.tooltiptext "Close Inspector">
|
<!ENTITY inspectCloseButton.tooltiptext "Close Inspector">
|
||||||
|
|
||||||
<!ENTITY inspectorHTMLCopyInner.label "Copy Inner HTML">
|
<!ENTITY inspectorHTMLCopyInner.label "Copy Inner HTML">
|
||||||
|
|||||||
@@ -334,6 +334,12 @@ telemetryYesButtonAccessKey = Y
|
|||||||
telemetryNoButtonLabel = No
|
telemetryNoButtonLabel = No
|
||||||
telemetryNoButtonAccessKey = N
|
telemetryNoButtonAccessKey = N
|
||||||
|
|
||||||
|
# Webapps notification popup
|
||||||
|
webapps.install = Install
|
||||||
|
webapps.install.accesskey = I
|
||||||
|
#LOCALIZATION NOTE (webapps.requestInstall) %1$S is the web app name, %2$S is the site from which the web app is installed
|
||||||
|
webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
|
||||||
|
|
||||||
# Keyword.URL reset prompt
|
# Keyword.URL reset prompt
|
||||||
# LOCALIZATION NOTE (keywordPrompt.message):
|
# LOCALIZATION NOTE (keywordPrompt.message):
|
||||||
# - %1$S is brandShortName
|
# - %1$S is brandShortName
|
||||||
|
|||||||
@@ -25,3 +25,10 @@ breadcrumbs.siblings=Siblings
|
|||||||
ruleView.label=Rules
|
ruleView.label=Rules
|
||||||
ruleView.accesskey=R
|
ruleView.accesskey=R
|
||||||
ruleView.tooltiptext=View and Edit CSS
|
ruleView.tooltiptext=View and Edit CSS
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (inspectButton.tooltiptext):
|
||||||
|
# This button appears in the Inspector Toolbar. inspectButton is stateful,
|
||||||
|
# if it's pressed users can select an element with the mouse. Pressing the
|
||||||
|
# "Return" key # changes that state. %S is the keyboard shortcut (VK_RETURN in
|
||||||
|
# chrome://global/locale/keys.properties).
|
||||||
|
inspectButton.tooltiptext=Select element with mouse (%S)
|
||||||
|
|||||||
@@ -49,3 +49,75 @@ helpLinkTitle=Read the documentation for this property
|
|||||||
# entered into the rule view a warning icon is displayed. This text is used for
|
# entered into the rule view a warning icon is displayed. This text is used for
|
||||||
# the title attribute of the warning icon.
|
# the title attribute of the warning icon.
|
||||||
rule.warning.title=Invalid property value
|
rule.warning.title=Invalid property value
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (style.contextmenu.copyselection): The computed view's
|
||||||
|
# context menu copy entry.
|
||||||
|
style.contextmenu.copyselection=Copy selection
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (style.contextmenu.copyselection.accesskey): The computed
|
||||||
|
# view's context menu copy entry access key.
|
||||||
|
style.contextmenu.copyselection.accesskey=C
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (style.contextmenu.copydeclaration): The style inspector's
|
||||||
|
# context menu copy property entry allows a complete CSS property to be copied.
|
||||||
|
style.contextmenu.copydeclaration=Copy declaration line
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (style.contextmenu.copydeclaration.accesskey): The style
|
||||||
|
# inspector's context menu copy property access key.
|
||||||
|
style.contextmenu.copydeclaration.accesskey=D
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (style.contextmenu.copyproperty): The style inspector's
|
||||||
|
# context menu copy property name entry allows a CSS property name to be copied.
|
||||||
|
style.contextmenu.copyproperty=Copy property
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (style.contextmenu.copyproperty.accesskey): The style
|
||||||
|
# inspector's context menu copy property name access key.
|
||||||
|
style.contextmenu.copyproperty.accesskey=P
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (style.contextmenu.copypropertyvalue): The style inspector's
|
||||||
|
# context menu copy property value entry allows a CSS property name to be copied.
|
||||||
|
style.contextmenu.copypropertyvalue=Copy property value
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (style.contextmenu.copypropertyvalue.accesskey): The style
|
||||||
|
# inspector's context menu copy property value access key.
|
||||||
|
style.contextmenu.copypropertyvalue.accesskey=U
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.contextmenu.copyselection): The rule view's context
|
||||||
|
# menu copy entry.
|
||||||
|
rule.contextmenu.copyselection=Copy selection
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.contextmenu.copyselection.accesskey): The rule view's
|
||||||
|
# context menu copy entry access key.
|
||||||
|
rule.contextmenu.copyselection.accesskey=C
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.contextmenu.copyrule): The rule view's context menu
|
||||||
|
# copy rule entry allows a complete CSS rule to be copied.
|
||||||
|
rule.contextmenu.copyrule=Copy rule
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.contextmenu.copyrule.accesskey): The rule view's
|
||||||
|
# context menu copy rule access key.
|
||||||
|
rule.contextmenu.copyrule.accesskey=R
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.contextmenu.copydeclaration): The rule view's context
|
||||||
|
# menu copy property entry allows a complete CSS property to be copied.
|
||||||
|
rule.contextmenu.copydeclaration=Copy declaration line
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.contextmenu.copydeclaration.accesskey): The rule view's
|
||||||
|
# context menu copy property access key.
|
||||||
|
rule.contextmenu.copydeclaration.accesskey=D
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.contextmenu.copyproperty): The rule view's context
|
||||||
|
# menu copy property entry allows a CSS property name to be copied.
|
||||||
|
rule.contextmenu.copyproperty=Copy property
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.contextmenu.copyproperty.accesskey): The rule
|
||||||
|
# view's context menu copy property name access key.
|
||||||
|
rule.contextmenu.copyproperty.accesskey=P
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.contextmenu.copypropertyvalue): The rule view's
|
||||||
|
# context menu copy property entry allows a CSS property value to be copied.
|
||||||
|
rule.contextmenu.copypropertyvalue=Copy property value
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.contextmenu.copypropertyvalue.accesskey): The rule
|
||||||
|
# view's context menu copy property value access key.
|
||||||
|
rule.contextmenu.copypropertyvalue.accesskey=U
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user