Browse files

get the jquery test suite running ... still lots of tests failing/not…

… running
  • Loading branch information...
1 parent be13df3 commit b7ffe2cd0049e3bcf06efb147361b7349576202d @svenfuchs committed May 9, 2010
View
6 lib/taka.rb
@@ -3,5 +3,9 @@
require 'taka/dom'
require 'taka/version'
+require 'taka/level2/css.rb'
+require 'taka/level2/events.rb'
+require 'taka/level2/views.rb'
-require 'taka/level2/events.rb'
+require 'taka/window.rb'
+require 'taka/johnson.rb'
View
2 lib/taka/dom/attr.rb
@@ -15,7 +15,7 @@ def attributes
nil
end
- def nextSibling
+ def nextSibling
nil
end
end
View
2 lib/taka/dom/character_data.rb
@@ -6,7 +6,7 @@ def data
end
def data=(_)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#data="))
end
def length
View
71 lib/taka/dom/document.rb
@@ -16,7 +16,7 @@ def doctype
end
def implementation
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#implementation"))
end
def documentElement
@@ -77,64 +77,81 @@ def hasFeature type, version
end
def importNode(importedNode, deep)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#importNode"))
end
+
def createElementNS(namespaceURI, qualifiedName)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#createElementNS"))
end
+
def createAttributeNS(namespaceURI, qualifiedName)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#createAttributeNS"))
end
+
def getElementsByTagNameNS(namespaceURI, localName)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#getElementsByTagNameNS"))
end
def inputEncoding
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#inputEncoding"))
end
+
def xmlEncoding
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#xmlEncoding"))
end
+
def xmlStandalone
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#xmlStandalone"))
end
+
def xmlStandalone=(_)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#xmlStandalone="))
end
+
def xmlVersion
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#xmlVersion"))
end
+
def xmlVersion=(_)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#xmlVersion="))
end
+
def strictErrorChecking
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#strictErrorChecking"))
end
+
def strictErrorChecking=(_)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#strictErrorChecking="))
end
+
def documentURI
- raise(NotImplementedError.new)
+ @document_uri
end
- def documentURI=(_)
- raise(NotImplementedError.new)
+
+ def documentURI=(uri)
+ @document_uri = uri
end
+
def adoptNode(source)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#adoptNode"))
end
+
def domConfig
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#domConfig"))
end
+
def normalizeDocument
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#normalizeDocument"))
end
+
def renameNode(n, namespaceURI, qualifiedName)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#renameNode"))
end
def decorate node
nx = Nokogiri::XML
- list = {
+ nh = Nokogiri::HTML
+ map = {
nx::Node => [DOM::Element, DOM::Node],
nx::Element => [DOM::Element, DOM::Node],
nx::Attr => [DOM::Element, DOM::Node, DOM::Attr],
@@ -148,18 +165,20 @@ def decorate node
nx::DocumentFragment => [DOM::Element, DOM::Node, DOM::DocumentFragment],
nx::Comment => [DOM::Element, DOM::Node, DOM::Comment],
nx::Notation => [DOM::Element, DOM::Node, DOM::Notation],
- }[node.class]
+ nh::DocumentFragment => [DOM::Element, DOM::Node, DOM::DocumentFragment]
+ }
+ # map[nh::DocumentFragment] = map[nx::DocumentFragment]
+ list = map[node.class]
raise("Unknown type #{node.class.name}") unless list
list.each { |mod| node.extend(mod) }
node
end
- def js_property? name
- return true if [:body, :documentElement].include?(name)
- false
- end
+ # def js_property? name
+ # [:body, :documentElement, :nodeName].include?(name)
+ # end
end
end
end
View
64 lib/taka/dom/document_fragment.rb
@@ -1,6 +1,70 @@
module Taka
module DOM
module DocumentFragment
+ def self.parse(*args)
+ fragment = Nokogiri::HTML::DocumentFragment.parse(*args)
+ fragment.extend(DOM::Element)
+ fragment.extend(DOM::Node)
+ fragment.extend(DOM::DocumentFragment)
+ fragment.extend(Module.new {
+ def decorate node
+ node = super
+
+ if node.is_a?(Nokogiri::XML::NodeSet)
+ node.extend(DOM::HTML::Collection)
+ return node
+ end
+
+ node.extend(DOM::HTML::Element)
+ ({
+ 'table' => [DOM::HTML::TableElement],
+ 'tr' => [DOM::HTML::TableRowElement],
+ 'thead' => [DOM::HTML::TableSectionElement],
+ 'tfoot' => [DOM::HTML::TableSectionElement],
+ 'tbody' => [DOM::HTML::TableSectionElement],
+ 'a' => [DOM::HTML::AnchorElement],
+ 'applet' => [DOM::HTML::AppletElement],
+ 'area' => [DOM::HTML::AreaElement],
+ 'body' => [DOM::HTML::BodyElement],
+ 'form' => [DOM::HTML::FormElement],
+ 'button' => [DOM::HTML::ButtonElement],
+ 'select' => [DOM::HTML::SelectElement],
+ 'fieldset' => [DOM::HTML::FieldSetElement],
+ 'frame' => [DOM::HTML::FrameElement],
+ 'iframe' => [DOM::HTML::IFrameElement],
+ 'img' => [DOM::HTML::ImageElement],
+ 'input' => [DOM::HTML::InputElement],
+ 'isindex' => [DOM::HTML::IsIndexElement],
+ 'label' => [DOM::HTML::LabelElement],
+ 'legend' => [DOM::HTML::LegendElement],
+ 'li' => [DOM::HTML::LiElement],
+ 'link' => [DOM::HTML::LinkElement],
+ 'map' => [DOM::HTML::MapElement],
+ 'meta' => [DOM::HTML::MetaElement],
+ 'object' => [DOM::HTML::ObjectElement],
+ 'ol' => [DOM::HTML::OListElement],
+ 'option' => [DOM::HTML::OptionElement],
+ 'param' => [DOM::HTML::ParamElement],
+ 'pre' => [DOM::HTML::PreElement],
+ 'script' => [DOM::HTML::ScriptElement],
+ 'style' => [DOM::HTML::StyleElement],
+ 'th' => [DOM::HTML::TableCellElement],
+ 'td' => [DOM::HTML::TableCellElement],
+ 'col' => [DOM::HTML::ColElement],
+ 'colgroup' => [DOM::HTML::ColElement],
+ 'textarea' => [DOM::HTML::TextAreaElement],
+ 'ul' => [DOM::HTML::UListElement],
+ }[node.node_name] || []).each do |klass|
+ node.extend(klass)
+ end
+
+ node
+ end
+ })
+ fragment
+ end
+
+
def attributes
nil
end
View
23 lib/taka/dom/element.rb
@@ -77,28 +77,35 @@ def getElementsByTagName(name)
end
def getAttributeNS(namespaceURI, localName)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#getAttributeNS"))
end
+
def setAttributeNS(namespaceURI, qualifiedName, value)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#setAttributeNS"))
end
+
def removeAttributeNS(namespaceURI, localName)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#removeAttributeNS"))
end
+
def getAttributeNodeNS(namespaceURI, localName)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#getAttributeNodeNS"))
end
+
def setAttributeNodeNS(newAttr)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#setAttributeNodeNS"))
end
+
def getElementsByTagNameNS(namespaceURI, localName)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#getElementsByTagNameNS"))
end
+
def hasAttribute(name)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#hasAttribute"))
end
+
def hasAttributeNS(namespaceURI, localName)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#hasAttributeNS"))
end
end
end
View
5 lib/taka/dom/html/document.rb
@@ -5,6 +5,11 @@ module Document
def title
at('.//title').text
end
+
+ def title=(title)
+ node = at('.//title') # TODO create head and title nodes if missing
+ node.content = title
+ end
# Returns the URI of the page that linked to this page. The value is
# an empty string if the user navigated to the page directly (not
View
21 lib/taka/dom/html/element.rb
@@ -2,12 +2,24 @@ module Taka
module DOM
module HTML
module Element
+ def []=(key, value)
+ case value
+ when NilClass, FalseClass
+ value = ''
+ when TrueClass
+ value = key
+ # when Fixnum
+ # value = value.to_s
+ end
+ super
+ end
+
def id
getAttribute('id')
end
def className
- self['class']
+ self['className']
end
###
@@ -17,6 +29,13 @@ def innerHTML
inner_html
end
+ def innerHTML=(html)
+ document.fragment(html).children.each do |tag|
+ appendChild(tag)
+ document.decorate(tag)
+ end
+ end
+
def method_missing method, *args, &block
attribute = method.to_s.downcase
super unless key?(attribute)
View
136 lib/taka/dom/node.rb
@@ -22,7 +22,7 @@ module Node
XINCLUDE_START = 19
XINCLUDE_END = 20
DOCB_DOCUMENT_NODE = 21
-
+
def nodeName
return '#text' if text?
return '#comment' if comment?
@@ -72,11 +72,16 @@ def nodeValue= value
end
def nodeType
- node_type
+ case nodeType = node_type
+ when HTML_DOCUMENT_NODE
+ DOCUMENT_NODE
+ else
+ nodeType
+ end
end
def parentNode
- parent
+ respond_to?(:parent) ? parent : nil
end
def childNodes
@@ -214,45 +219,110 @@ def cloneNode deep
end
def normalize
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#normalize"))
end
def isSupported(feature, version)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#isSupported"))
end
def namespaceURI
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#namespaceURI"))
end
def prefix
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#prefix"))
end
def prefix=(_)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#prefix="))
end
def localName
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#localName"))
end
def hasAttributes
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#hasAttributes"))
end
+ # http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-baseURI
+ # The absolute base URI of this node or null if the implementation wasn't
+ # able to obtain an absolute URI. This value is computed as described in
+ # Base URIs. However, when the Document supports the feature "HTML" [DOM
+ # Level 2 HTML], the base URI is computed using first the value of the
+ # href attribute of the HTML BASE element if any, and the value of the
+ # documentURI attribute from the Document interface otherwise.
+ #
+ # Relative paths in the document are relative to the base URL. The base
+ # URL is the location of the current document by default, but it can be
+ # overridden by the base tag.
+
def baseURI
- raise(NotImplementedError.new)
+ base = at('.//base')
+ base ? base['href'] : document.documentURI
+ end
+
+ def contains(other)
+ other == self || other.ancestors.include?(self)
end
- DOCUMENT_POSITION_DISCONNECTED = 0
- DOCUMENT_POSITION_PRECEDING = 0
- DOCUMENT_POSITION_FOLLOWING = 0
- DOCUMENT_POSITION_CONTAINS = 0
- DOCUMENT_POSITION_CONTAINED_BY = 0
- DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0
+ DOCUMENT_POSITION_EQUAL = 0
+ DOCUMENT_POSITION_DISCONNECTED = 1
+ DOCUMENT_POSITION_PRECEDING = 2
+ DOCUMENT_POSITION_FOLLOWING = 4
+ DOCUMENT_POSITION_CONTAINS = 8
+ DOCUMENT_POSITION_CONTAINED_BY = 16
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 32
+
+
def compareDocumentPosition(other)
- raise(NotImplementedError.new)
+ # raise(NotImplementedError.new("not implemented: #{self.class.name}#compareDocumentPosition"))
+
+ return DOCUMENT_POSITION_EQUAL if self == other
+
+ return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_DISCONNECTED if ownerDocument != other.ownerDocument
+
+ parentNode.childNodes.each do |sibling|
+ if sibling == self
+ return DOCUMENT_POSITION_FOLLOWING
+ elsif sibling == other
+ return DOCUMENT_POSITION_PRECEDING
+ end
+ end if parentNode == other.parentNode
+
+ return DOCUMENT_POSITION_CONTAINED_BY | DOCUMENT_POSITION_FOLLOWING if contains(other)
+ return DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING if other.contains(self)
+
+ aparents = ancestors
+
+ bparents = [];
+ parent = other.parentNode;
+
+ while(parent)
+ i = aparents.index(parent);
+ if i.nil?
+ bparents[bparents.length] = parent;
+ parent = parent.parentNode;
+ else
+ if bparents.length > aparents.length
+ return DOCUMENT_POSITION_FOLLOWING;
+ elsif bparents.length < aparents.length
+ return DOCUMENT_POSITION_PRECEDING;
+ else
+ # common ancestor diverge point
+ if i === 0
+ return DOCUMENT_POSITION_FOLLOWING;
+ else
+ parent = aparents[i - 1]
+ end
+ return parent.compareDocumentPosition(bparents.pop);
+ end
+ end
+ end
+
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_DISCONNECTED
end
def textContent
@@ -264,29 +334,35 @@ def textContent= string
end
def isSameNode(other)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#isSameNode"))
end
def lookupPrefix(namespaceURI)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#lookupPrefix"))
end
+
def isDefaultNamespace(namespaceURI)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#isDefaultNamespace"))
end
+
def lookupNamespaceURI(prefix)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#lookupNamespaceURI"))
end
+
def isEqualNode(arg)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#isEqualNode"))
end
+
def getFeature(feature, version)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#getFeature"))
end
+
def setUserData(key, data, handler)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#setUserData"))
end
+
def getUserData(key)
- raise(NotImplementedError.new)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#getUserData"))
end
###
@@ -340,10 +416,10 @@ def can_append? new_child
true
end
- def js_property? name
- return true if [:firstChild].include?(name)
- false
- end
+ # def js_property? name
+ # return true if [:firstChild, :nodeName].include?(name)
+ # false
+ # end
end
end
View
17 lib/taka/dom/node_list.rb
@@ -5,13 +5,30 @@ def initialize &block
@block = block
end
+ def [](key)
+ @block.call[key]
+ end
+
+ def length
+ @block.call.count
+ end
+
def item(index)
@block.call[index]
end
+ # apparently can run into an endless loop
+ # def respond_to? name
+ # @block.call.respond_to?(name)
+ # end
+
def method_missing name, *args, &block
@block.call.send(name, *args, &block)
end
+
+ # def js_property?(name)
+ # [:length].include?(name)
+ # end
end
end
end
View
96 lib/taka/johnson.rb
@@ -0,0 +1,96 @@
+map = {
+ Taka::DOMException => [:code, :message],
+ Taka::DOM::Document => [:doctype, :implementation, :documentElement],
+ Taka::DOM::Node => [:nodeName, :nodeValue, :nodeType, :parentNode, :childNodes, :firstChild, :lastChild, :previousSibling, :nextSibling, :attributes, :ownerDocument, :namespaceURI, :prefix, :localName],
+ Taka::DOM::NodeList => [:length],
+ Taka::DOM::NamedNodeMap => [:length],
+ Taka::DOM::CharacterData => [:data, :length],
+ Taka::DOM::Attr => [:name, :specified, :value, :ownerElement],
+ Taka::DOM::Element => [:tagName],
+ Taka::DOM::DTD => [:name, :entities, :notations, :publicId, :systemId, :internalSubset],
+ Taka::DOM::Notation => [:publicId, :systemId],
+ Taka::DOM::EntityDecl => [:publicId, :systemId, :notationName],
+ Taka::DOM::ProcessingInstruction => [:target, :data],
+
+ Taka::DOM::HTML::Collection => [:length],
+ Taka::DOM::HTML::Document => [:title, :referrer, :domain, :URL, :body, :images, :applets, :links, :forms, :anchors, :cookie],
+ Taka::DOM::HTML::Element => [:id, :title, :lang, :dir, :className],
+ Taka::DOM::HTML::LinkElement => [:disabled, :charset, :href, :hreflang, :media, :rel, :rev, :target, :type],
+ Taka::DOM::HTML::MetaElement => [:content, :httpEquiv, :name, :scheme],
+ Taka::DOM::HTML::IsIndexElement => [:form, :prompt],
+ Taka::DOM::HTML::StyleElement => [:disabled, :media, :type],
+ Taka::DOM::HTML::BodyElement => [:aLink, :background, :bgColor, :link, :text, :vLink],
+ Taka::DOM::HTML::FormElement => [:elements, :length, :name, :acceptCharset, :action, :enctype, :method, :target],
+ Taka::DOM::HTML::SelectElement => [:type, :selectedIndex, :value, :length, :form, :options, :disabled, :multiple, :name, :size, :tabIndex],
+ Taka::DOM::HTML::OptionElement => [:form, :defaultSelected, :text, :index, :disabled, :label, :selected, :value],
+ Taka::DOM::HTML::InputElement => [:defaultValue, :defaultChecked, :form, :accept, :accessKey, :align, :alt, :checked, :disabled, :maxLength, :name, :readOnly, :size, :src, :tabIndex, :type, :useMap, :value],
+ Taka::DOM::HTML::TextAreaElement => [:defaultValue, :form, :accessKey, :cols, :disabled, :name, :readOnly, :rows, :tabIndex, :type, :value],
+ Taka::DOM::HTML::ButtonElement => [:form, :accessKey, :disabled, :name, :tabIndex, :type, :value],
+ Taka::DOM::HTML::LabelElement => [:form, :accessKey, :htmlFor],
+ Taka::DOM::HTML::FieldSetElement => [:form],
+ Taka::DOM::HTML::LegendElement => [:form, :accessKey, :align],
+ Taka::DOM::HTML::UListElement => [:compact, :type],
+ Taka::DOM::HTML::OListElement => [:compact, :start, :type],
+ Taka::DOM::HTML::LiElement => [:type, :value],
+ Taka::DOM::HTML::PreElement => [:width],
+ Taka::DOM::HTML::AnchorElement => [:accessKey, :charset, :coords, :href, :hreflang, :name, :rel, :rev, :shape, :tabIndex, :target, :type],
+ Taka::DOM::HTML::ImageElement => [:name, :align, :alt, :border, :height, :hspace, :isMap, :longDesc, :src, :useMap, :vspace, :width],
+ Taka::DOM::HTML::ObjectElement => [:form, :code, :align, :archive, :border, :codeBase, :codeType, :data, :declare, :height, :hspace, :name, :standby, :tabIndex, :type, :useMap, :vspace, :width, :contentDocument],
+ Taka::DOM::HTML::ParamElement => [:name, :type, :value, :valueType],
+ Taka::DOM::HTML::AppletElement => [:align, :alt, :archive, :code, :codeBase, :height, :hspace, :name, :object, :vspace, :width],
+ Taka::DOM::HTML::MapElement => [:areas, :name],
+ Taka::DOM::HTML::AreaElement => [:accessKey, :alt, :coords, :href, :noHref, :shape, :tabIndex, :target],
+ Taka::DOM::HTML::ScriptElement => [:text, :htmlFor, :event, :charset, :defer, :src, :type],
+ Taka::DOM::HTML::TableElement => [:rows, :tBodies, :align, :bgColor, :border, :cellPadding, :cellSpacing, :frame, :rules, :summary, :width],
+ Taka::DOM::HTML::TableSectionElement => [:align, :ch, :chOff, :vAlign, :rows],
+ Taka::DOM::HTML::TableRowElement => [:rowIndex, :sectionRowIndex, :cells, :align, :bgColor, :ch, :chOff, :vAlign],
+ Taka::DOM::HTML::TableCellElement => [:cellIndex, :abbr, :align, :axis, :bgColor, :ch, :chOff, :colSpan, :headers, :height, :noWrap, :rowSpan, :scope, :vAlign, :width],
+ Taka::DOM::HTML::FrameElement => [:frameBorder, :longDesc, :marginHeight, :marginWidth, :name, :noResize, :scrolling, :src],
+ Taka::DOM::HTML::IFrameElement => [:align, :frameBorder, :height, :longDesc, :marginHeight, :marginWidth, :name, :scrolling, :src, :width, :contentDocument],
+
+ Taka::Event => [:type, :target, :currentTarget, :eventPhase, :bubbles, :cancelable, :timeStamp],
+ Taka::EventException => [:code],
+
+ Taka::Window => [:location, :navigator, :console, :parent, :name, :document, :defaultStatus, :history, :opener, :frames, :innerHeight, :innerWidth, :outerHeight, :outerWidth, :pageXOffset, :pageYOffset, :screenX, :screenY, :screenLeft, :screenTop],
+ Taka::Window::Location => [:hash, :host, :hostName, :href, :pathname, :port, :protocol, :search],
+ Taka::Window::Frame => [:contentWindow],
+
+ Exception => [:code, :message],
+
+ # Taka::DOM::HTML::OptionsCollection => [:length],
+ # Taka::DOM::HTML::HtmlElement => [:version],
+ # Taka::DOM::HTML::HeadElement => [:profile],
+ # Taka::DOM::HTML::TitleElement => [:text],
+ # Taka::DOM::HTML::BaseElement => [:href, :target],
+ # Taka::DOM::HTML::OptGroupElement => [:disabled, :label],
+ # Taka::DOM::HTML::DListElement => [:compact],
+ # Taka::DOM::HTML::DirectoryElement => [:compact],
+ # Taka::DOM::HTML::MenuElement => [:compact],
+ # Taka::DOM::HTML::DivElement => [:align],
+ # Taka::DOM::HTML::ParagraphElement => [:align],
+ # Taka::DOM::HTML::HeadingElement => [:align],
+ # Taka::DOM::HTML::QuoteElement => [:cite],
+ # Taka::DOM::HTML::BRElement => [:clear],
+ # Taka::DOM::HTML::BaseFontElement => [:color, :face, :size],
+ # Taka::DOM::HTML::FontElement => [:color, :face, :size],
+ # Taka::DOM::HTML::HRElement => [:align, :noShade, :size, :width],
+ # Taka::DOM::HTML::ModElement => [:cite, :dateTime],
+ # Taka::DOM::HTML::TableCaptionElement => [:align],
+ # Taka::DOM::HTML::TableColElement => [:align, :ch, :chOff, :span, :vAlign, :width],
+ # Taka::DOM::HTML::FrameSetElement => [:cols, :rows],
+
+ # Taka::UIEvent => [:view, :detail],
+ # Taka::MouseEvent => [:screenX, :screenY, :clientX, :clientY, :ctrlKey, :shiftKey, :altKey, :metaKey, :button, :relatedTarget],
+ # Taka::MutationEvent => [:relatedNode, :prevValue, :newValue, :attrName, :attrChange]
+}
+
+map.each do |const, js_properties|
+ const.const_set(:JS_PROPERTIES, js_properties)
+ const.class_eval <<-code
+ def js_property?(name)
+ JS_PROPERTIES.include?(name) || super
+ rescue
+ false
+ end
+ code
+end
View
14 lib/taka/level2/css.rb
@@ -0,0 +1,14 @@
+# CSSStyleDeclaration
+
+module Taka
+ class CSSStyleDeclaration
+ end
+
+ module ElementCSSInlineStyle
+ def style
+ @style ||= CSSStyleDeclaration.new
+ end
+ end
+end
+
+Taka::DOM::HTML::Element.send(:include, Taka::ElementCSSInlineStyle)
View
3 lib/taka/level2/events.rb
@@ -2,6 +2,9 @@
require 'taka/level2/events/event_exception.rb'
require 'taka/level2/events/event_listener.rb'
require 'taka/level2/events/event_target.rb'
+require 'taka/level2/events/mouse_event.rb'
+require 'taka/level2/events/mutation_event.rb'
+require 'taka/level2/events/ui_event.rb'
require 'taka/level2/events/dom/document.rb'
Taka::DOM::Document.send(:include, Taka::EventTarget)
View
4 lib/taka/level2/events/event_listener.rb
@@ -1,7 +1,3 @@
-# interface EventListener {
-# void handleEvent(in Event evt);
-# };
-
module Taka
module EventListener
def handleEvent(event)
View
45 lib/taka/level2/events/event_target.rb
@@ -17,28 +17,55 @@ def dispatchEvent(event)
end
event.target = self
- ancestors.reverse.dup.each { |ancestor| ancestor._dispatch(Event::CAPTURING_PHASE, event) }
- _dispatch(Event::AT_TARGET, event)
- # evaluate_js(self["on#{event.type}"]) if self["on#{event.type}"]
- ancestors.dup.each { |node| node._dispatch(Event::BUBBLING_PHASE, event) } if event.bubbles
- # execute_default_event_behaviour unless event.cancelled
+ capture_event(event)
+ dispatch_event(Event::AT_TARGET, event)
+ evaluate_event_attribute(event)
+ bubble_event(event) if event.bubbles
+ execute_default_behaviour unless event.cancelled
event.cancelled
end
protected
+
+ def capture_event(event)
+ ancestors.reverse.dup.each do |ancestor|
+ ancestor.dispatch_event(Event::CAPTURING_PHASE, event)
+ break if event.propagation_stopped
+ end if respond_to?(:ancestors)
+ end
+
+ def bubble_event(event)
+ ancestors.dup.each do |node|
+ node.dispatch_event(Event::BUBBLING_PHASE, event)
+ break if event.propagation_stopped
+ end if respond_to?(:ancestors)
+ end
- def _dispatch(phase, event)
+ def dispatch_event(phase, event)
return if event.propagation_stopped
event.eventPhase = phase
event.currentTarget = self
-
+
listeners(event.type, event.eventPhase == Event::CAPTURING_PHASE).dup.each do |listener|
- event.stopPropagation unless listener.handleEvent(event)
- break if event.propagation_stopped
+ event.stopPropagation unless call_listener(listener, event)
end
end
+
+ def call_listener(listener, event)
+ # https://developer.mozilla.org/en/DOM/element.addEventListener
+ # [listener] must be an object implementing the EventListener interface, or simply a JavaScript function.
+ listener.respond_to?(:handleEvent) ? listener.handleEvent(event) : listener.call(event)
+ end
+
+ def evaluate_event_attribute(event)
+ evaluate_js(self["on#{event.type}"]) if respond_to?(:[]) && self["on#{event.type}"]
+ end
+
+ def execute_default_behaviour
+ # TODO
+ end
def listeners(type, use_capture)
phase = use_capture ? Event::CAPTURING_PHASE : Event::BUBBLING_PHASE
View
20 lib/taka/level2/events/mouse_event.rb
@@ -0,0 +1,20 @@
+module Taka
+ class MouseEvent < Event
+ attr_accessor :screenX, :screenY, :clientX, :clientY, :ctrlKey, :shiftKey,
+ :altKey, :metaKey, :button, :relatedTarget
+
+ def initMouseEvent(type, canBubble, cancelable, view, detail, screenX, screenY,
+ clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#initMouseEvent"))
+ end
+
+ def getModifierState(keyIdentifier)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#getModifierState"))
+ end
+
+ def initMouseEventNS(namespaceURI, type, canBubble, cancelable, view, detail,
+ screenX, screenY, clientX, clientY, button, relatedTarget, modifiersList)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#initMouseEventNS"))
+ end
+ end
+end
View
17 lib/taka/level2/events/mutation_event.rb
@@ -0,0 +1,17 @@
+module Taka
+ class MutationEvent < Event
+ MODIFICATION = 1
+ ADDITION = 2
+ REMOVAL = 3
+
+ attr_accessor :relatedNode, :prevValue, :newValue, :attrName, :attrChange
+
+ def initMutationEvent(type, canBubble, cancelable, relatedNode, prevValue, newValue, attrName, attrChange)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#initMutationEvent"))
+ end
+
+ def initMutationEventNS(namespaceURI, type, canBubble, cancelable, relatedNode, prevValue, newValue, attrName, attrChange)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#initMutationEventNS"))
+ end
+ end
+end
View
13 lib/taka/level2/events/ui_event.rb
@@ -0,0 +1,13 @@
+module Taka
+ class UiEvent < Event
+ attr_accessor :view, :detail
+
+ def initUIEvent(type, canBubble, cancelable, view, detail)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#initUIEvent"))
+ end
+
+ def initUIEventNS(namespaceURI, type, canBubble, cancelable, view, detail)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#initUIEventNS"))
+ end
+ end
+end
View
3 lib/taka/level2/views.rb
@@ -0,0 +1,3 @@
+require 'taka/level2/views/document_view.rb'
+
+Taka::DOM::HTML::Document.send(:include, Taka::DocumentView)
View
5 lib/taka/level2/views/document_view.rb
@@ -0,0 +1,5 @@
+module Taka
+ module DocumentView
+ attr_accessor :defaultView
+ end
+end
View
151 lib/taka/window.rb
@@ -0,0 +1,151 @@
+require 'open-uri'
+require 'johnson/tracemonkey'
+
+require 'taka/window/console.rb'
+require 'taka/window/frame.rb'
+require 'taka/window/history.rb'
+require 'taka/window/location.rb'
+require 'taka/window/navigator.rb'
+require 'taka/window/screen.rb'
+require 'taka/window/timers.rb'
+
+module Taka
+ class Window
+ include Taka::EventTarget
+ include Taka::Window::Timers
+
+ class << self
+ def open(url, name)
+ # window = Window.new
+ # window.name = name
+ # window.location.assign(url)
+ # window
+ end
+ end
+
+ attr_accessor :parent, :name, :document, :defaultStatus, :history, :opener, :frames,
+ :innerHeight, :innerWidth, :outerHeight, :outerWidth, :pageXOffset, :pageYOffset,
+ :screenX, :screenY, :screenLeft, :screenTop
+
+ def initialize(name = 'window', parent = nil, opener = nil)
+ @name = name
+ @parent = parent || self
+ @opener = opener
+ @frames = []
+ @screen = Screen.new(self)
+ @history = History.new
+ end
+
+ def log(line)
+ console.log(line)
+ end
+
+ def print(line)
+ puts line
+ end
+
+ def runtime
+ @runtime ||= Johnson::Runtime.new.tap do |runtime|
+ runtime['window'] = self
+ runtime['document'] = document
+ runtime['location'] = location
+ runtime['navigator'] = navigator
+ runtime['console'] = console
+ end
+ end
+
+ def load(arg)
+ arg = arg.gsub(%r(^file://), '')
+ uri, document = uri?(arg) || file?(arg) ? [arg, open(arg).read] : ['', arg]
+ load_document(document, uri)
+ load_scripts
+ load_frames
+ trigger_load_event
+ Window::Timers::Task.run_all
+ end
+
+ def evaluate(script, file = nil, line = nil)
+ runtime.evaluate(script, file, line, self, self)
+ end
+
+ def normalize_uri(uri)
+ location.uri.normalize.merge(uri)
+ end
+
+ def close
+ end
+
+ def location
+ @location ||= Location.new(self)
+ end
+
+ def location=(uri)
+ if location.href == uri
+ location.reload
+ elsif location.href == 'about:blank'
+ location.assign(uri)
+ else
+ location.replace(uri)
+ end
+ end
+
+ def navigator
+ @navigator ||= Navigator.new
+ end
+
+ def getComputedStyle
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#getComputedStyle"))
+ end
+
+ def console
+ @console ||= Console.new
+ end
+
+ protected
+
+ def load_document(document, uri)
+ flags = 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6
+ self.document = Taka::DOM.HTML(document, uri, nil, flags)
+ end
+
+ def load_scripts
+ document.getElementsByTagName('script').each do |script|
+ script['src'] ? load_script(script['src']) : evaluate(script.textContent)
+ end
+ end
+
+ def load_script(uri)
+ script = open(normalize_uri(uri))
+ script = script.string if script.respond_to?(:string)
+ script = script.read if script.respond_to?(:read)
+ evaluate(script, uri)
+ end
+
+ def load_frames
+ document.getElementsByTagName('iframe').each { |frame| load_frame(frame) }
+ end
+
+ def load_frame(node)
+ frame = Frame.new(node['name'], self)
+ frame.location.href = normalize_uri(node['src']) if node['src']
+ frames << frame
+ end
+
+ def trigger_load_event
+ event = document.createEvent('Events')
+ event.initEvent('load')
+ dispatchEvent(event)
+ end
+
+ def uri?(arg)
+ uri = URI.parse(arg)
+ %w(file http https).include?(uri.scheme)
+ rescue
+ false
+ end
+
+ def file?(arg)
+ arg.to_s[0, 1] == '/'
+ end
+ end
+end
View
22 lib/taka/window/console.rb
@@ -0,0 +1,22 @@
+module Taka
+ class Window
+ class Console
+ def log(*args)
+ # p args.first.item(0)
+ @log ||= []
+ args.empty? ? @log : @log << args
+ end
+
+ alias_method :debug, :log
+ alias_method :info, :log
+ alias_method :warn, :log
+ alias_method :error, :log
+
+ def print
+ log.each do |line|
+ puts line.map { |arg| arg.to_s }.join(', ')
+ end
+ end
+ end
+ end
+end
View
9 lib/taka/window/frame.rb
@@ -0,0 +1,9 @@
+module Taka
+ class Window
+ class Frame < Window
+ def contentWindow
+ parent
+ end
+ end
+ end
+end
View
6 lib/taka/window/history.rb
@@ -0,0 +1,6 @@
+module Taka
+ class Window
+ class History < Array
+ end
+ end
+end
View
115 lib/taka/window/location.rb
@@ -0,0 +1,115 @@
+require 'uri'
+
+module Taka
+ class Window
+ class Location
+ attr_reader :uri, :href, :window
+
+ def initialize(window)
+ @window = window
+ end
+
+ def history
+ window.history
+ end
+
+ def href=(url)
+ @uri = parse_uri(url)
+ history << url
+ reload
+ end
+ alias :assign :href=
+
+ def replace(url)
+ @uri = parse_uri(url)
+ reload
+ end
+
+ def reload
+ @href = uri.to_s
+ window.load(href)
+ end
+
+ # def set(uri)
+ # @uri = parse_uri(uri)
+ # @href = uri.to_s
+ # end
+
+ def hash
+ "##{uri.fragment}"
+ end
+
+ def hash=(hash)
+ uri.fragment = hash.gsub(/^#/, '')
+ reload
+ end
+
+ def host
+ "#{uri.host}:#{uri.port}"
+ end
+
+ def host=(host)
+ uri.host, uri.port = host.split(':')
+ reload
+ end
+
+ def hostname
+ uri.host
+ end
+
+ def hostname=(hostname)
+ uri.host = hostname
+ reload
+ end
+
+ def pathname
+ uri.path
+ end
+
+ def pathname=(pathname)
+ pathname = "/#{pathname}" unless pathname =~ /^\//
+ uri.path = pathname
+ reload
+ end
+
+ def port
+ uri.port.to_s
+ end
+
+ def port=(port)
+ uri.port = port
+ reload
+ end
+
+ def protocol
+ "#{uri.scheme}:"
+ end
+
+ def protocol=(protocol)
+ uri.scheme = protocol
+ reload
+ end
+
+ def search
+ "?#{uri.query}"
+ end
+
+ def search=(search)
+ uri.query = search.gsub(/^\?/, '')
+ reload
+ end
+
+ def toString
+ href
+ end
+
+ protected
+
+ def parse_uri(uri)
+ uri = uri.is_a?(URI) ? uri : URI.parse(uri)
+ (class << uri; self; end).send(:define_method, :default_port) { 0 }
+ uri
+ end
+ end
+ end
+end
View
45 lib/taka/window/navigator.rb
@@ -0,0 +1,45 @@
+module Taka
+ class Window
+ class Navigator
+ attr_reader :appCodeName, :appName, :appVersion, :buildID, :cookieEnabled,
+ :language, :mimeTypes, :onLine, :oscpu, :plattform, :plugins, :product,
+ :productSub, :securityPolicy, :userAgent, :vendor, :vendorSub,
+ :javaEnabled, :mozIsLocallyAvailable, :taintEnabled
+
+ def initialize
+ @appCodeName = '' # the internal "code" name of the current browser.
+ @appName = '' # the official name of the browser.
+ @appVersion = '' # the version of the browser as a string.
+ @buildID = '' # the build identifier of the browser (e.g. "2006090803")
+ @cookieEnabled = true # a boolean indicating whether cookies are enabled in the browser or not.
+ @language = '' # a string representing the language version of the browser.
+ @mimeTypes = '' # a list of the MIME types supported by the browser.
+ @onLine = true # a boolean indicating whether the browser is working online.
+ @oscpu = '' # a string that represents the current operating system.
+ @platform = '' # a string representing the platform of the browser.
+ @plugins = [] # an array of the plugins installed in the browser.
+ @product = '' # the product name of the current browser. (e.g. "Gecko")
+ @productSub = '' # the build number of the current browser (e.g. "20060909")
+ @securityPolicy = '' # an empty string. In Netscape 4.7x, "US & CA domestic policy" or "Export policy".
+ @userAgent = '' # the user agent string for the current browser.
+ @vendor = '' # the vendor name of the current browser (e.g. "Netscape6")
+ @vendorSub = '' # the vendor version number (e.g. "6.1")
+ @javaEnabled = true # Indicates whether the host browser is Java-enabled or not.
+ @taintEnabled = false # JavaScript taint/untaint functions removed in JavaScript 1.2
+ @mozIsLocallyAvailable = true # Lets code check to see if the document at a given URI is available without using the network.
+ end
+
+ def preference(name, value)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#preference"))
+ end
+
+ def registerContentHandler(mimeType, uri, title)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#registerContentHandler"))
+ end
+
+ def registerProtocolHandler(protocol, uri, title)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#registerProtocolHandler"))
+ end
+ end
+ end
+end
View
9 lib/taka/window/screen.rb
@@ -0,0 +1,9 @@
+module Taka
+ class Window
+ class Screen
+ def initialize(window)
+ @window = window
+ end
+ end
+ end
+end
View
76 lib/taka/window/timers.rb
@@ -0,0 +1,76 @@
+module Taka
+ class Window
+ module Timers
+ class Task
+ class << self
+ def run_all
+ until tasks.empty?
+ handle, task = tasks.to_a.last
+ remove(handle)
+ task.process
+ end
+ end
+
+ def schedule(handler, delay, *args)
+ handle = next_handle
+ tasks[handle] = new(handler, delay, args)
+ handle
+ end
+
+ def remove(handle)
+ tasks.delete(handle)
+ end
+
+ def next_handle
+ @@next_handle ||= 0
+ @@next_handle =+ 1
+ end
+
+ def tasks
+ @@tasks ||= {}
+ end
+ end
+
+ attr_reader :handler, :args, :run_at, :thread
+
+ def initialize(handler, delay, args)
+ @handler, @args = handler, args
+ @run_at = Time.now + delay.to_f / 1000
+ # schedule! # gives: RuntimeError: Johnson is not thread safe ...
+ end
+
+ def schedule!
+ @thread = Thread.new do
+ sleep(0.1) until due?
+ process
+ end
+ thread.join
+ end
+
+ def due?
+ Time.now > run_at
+ end
+
+ def process
+ handler.call(*args)
+ end
+ end
+
+ def setTimeout(handler, delay, *args)
+ Window::Timers::Task.schedule(handler, delay, *args)
+ end
+
+ def clearTimeout(handle)
+ Window::Timers::Task.remove(handle)
+ end
+
+ def setInterval(handler, timeout, *args)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#setInterval"))
+ end
+
+ def clearInterval(handle)
+ raise(NotImplementedError.new("not implemented: #{self.class.name}#clearInterval"))
+ end
+ end
+ end
+end
View
6,241 test/dom/jquery-1.4.2.js
6,241 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
57 test/dom/jquery_test.rb
@@ -0,0 +1,57 @@
+require File.expand_path('../../test_helper', __FILE__)
+
+require 'webmock/test_unit'
+
+JQUERY_PATH = File.expand_path('../../../vendor/jquery/', __FILE__)
+
+# class JQueryTest < Test::Unit::TestCase
+# include WebMock
+#
+# attr_reader :window
+#
+# def setup
+# @window = Taka::Window.new
+# window.location.instance_variable_set(:@uri, URI.parse('http://example.org/test/'))
+# stub_request(:any, /./).to_return do |request|
+# # puts "loading #{request.uri.path} ..."
+# { :body => File.open("#{JQUERY_PATH}#{request.uri.path}") { |f| f.read } }
+# end
+# end
+#
+# test "load loads an html document" do
+# window.load("http://example.org/test/index.html")
+# result = window.evaluate <<-js
+# jQuery('#qunit-tests ol li').toArray()
+# js
+# result.each do |tag|
+# p tag.className
+# end
+# end
+# end
+
+
+include WebMock
+stub_request(:any, /./).to_return do |request|
+ # puts "loading #{request.uri.path}"
+ { :body => File.open("#{JQUERY_PATH}#{request.uri.path}") { |f| f.read } }
+end
+
+class JQueryTest < Test::Unit::TestCase
+ window = Taka::Window.new
+ window.location.instance_variable_set(:@uri, URI.parse('http://example.org/test/'))
+
+ window.load("http://example.org/test/index.html")
+
+ # puts window.document.getElementById("qunit-tests")
+ result = window.evaluate("jQuery('#qunit-tests > li').toArray()")
+ count = 0
+
+ result.each do |tag|
+ _module = tag.firstChild.innerHTML =~ /^([^<]*)/ && $1.strip
+ tag.getElementsByTagName('li').each do |assertion|
+ test("#{count += 1} #{_module}: #{assertion.textContent}") do
+ flunk("#{_module}: #{assertion.textContent}") if assertion.className == 'fail'
+ end
+ end
+ end
+end
View
2 test/dom/level2/events/event_test.rb → test/dom/level2-events_test.rb
@@ -1,4 +1,4 @@
-require File.expand_path('../../../../test_helper', __FILE__)
+require File.expand_path('../../test_helper', __FILE__)
class Level2EventsTest < Test::Unit::TestCase
attr_reader :doc, :body, :foo, :event
View
46 test/dom/level2-views_test.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../test_helper', __FILE__)
+
+class Level2EventsTest < Test::Unit::TestCase
+ attr_reader :window
+
+ def setup
+ @window = Taka::Window.new
+ end
+
+ test "Window implements the EventTarget interface" do
+ assert window.respond_to?(:addEventListener)
+ assert window.respond_to?(:removeEventListener)
+ assert window.respond_to?(:dispatchEvent)
+ end
+
+ test "Window#parent: If a window does not have a parent, its parent property is a reference to itself" do
+ assert_equal window, window.parent
+ end
+
+ test "Window#parent: When a window is loaded in an <iframe> its parent is the window with the element embedding the window" do
+ end
+
+ test "Window#location: returns the Location object" do
+ end
+
+ test "Window#setTimeout: Executes a code snippet after specified delay." do
+ # var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
+ # var timeoutID = window.setTimeout(code, delay);
+ # where
+ #
+ # timeoutID is the ID of the timeout, which can be used later with window.clearTimeout.
+ # func is the function you want to execute after delay milliseconds.
+ # code in the alternate syntax, is a string of code you want to execute after delay milliseconds. (Using this syntax is not recommended for the same reasons as using eval())
+ # delay is the number of milliseconds (thousandths of a second) that the function call should be delayed by.
+ end
+
+ test "Window#setTimeout: Executes a function after specified delay." do
+ end
+
+ test "Window#getComputedStyle: returns the computed style of an element" do
+ # var style = window.getComputedStyle(element, pseudoElt);
+ # element is an element.
+ # pseudoElt is a string specifying the pseudo-element to match. Must be null for regular elements.
+ # style is a CSSStyleDeclaration object.
+ end
+end
View
120 test/dom/location_test.rb
@@ -0,0 +1,120 @@
+require File.expand_path('../../test_helper', __FILE__)
+
+class LocationTest < Test::Unit::TestCase
+ class Window
+ attr_reader :url
+ def load(url)
+ @url = url
+ end
+ end
+
+ attr_reader :google, :location, :window
+
+ def setup
+ @google = 'http://www.google.com:80/search?q=devmo#test'
+ @window = Window.new
+ @location = Taka::Location.new(window, Taka::Window::History.new)
+ location.href = google
+ end
+
+ test "Location#hash: returns the the part of the URL that follows the # symbol, including the # symbol" do
+ assert_equal '#test', location.hash
+ end
+
+ test "Location#host: returns the host name and port number" do
+ assert_equal 'www.google.com:80', location.host
+ end
+
+ test "Location#hostname: returns the host name (without the port number or square brackets)" do
+ assert_equal 'www.google.com', location.hostname
+ end
+
+ test "Location#href: returns the entire URL" do
+ assert_equal 'http://www.google.com:80/search?q=devmo#test', location.href
+ end
+
+ test "Location#pathname: returns the path (relative to the host)" do
+ assert_equal '/search', location.pathname
+ end
+
+ test "Location#port: returns the port number of the URL" do
+ assert_equal '80', location.port
+ end
+
+ test "Location#protocol: returns the protocol of the URL" do
+ assert_equal 'http:', location.protocol
+ end
+
+ test "Location#search: returns the part of the URL that follows the ? symbol, including the ? symbol" do
+ assert_equal '?q=devmo', location.search
+ end
+
+ test "Location#assign(url): Load the document at the provided URL" do
+ github = 'http://github.com:80'
+ location.assign(github)
+
+ assert_equal github, window.url
+ assert_equal github, location.href
+
+ assert_equal google, location.history.first
+ assert_equal github, location.history.last
+ end
+
+ test "Location#reload(forceget): Reload the document from the current URL." do
+ # forceget is a boolean, which, when it is true, causes the page to always be reloaded from the server.
+ # If it is false or not specified, the browser may reload the page from its cache
+ end
+
+ test "Location#replace(url): Replace the current document with the one at the provided URL" do
+ github = 'http://github.com:80'
+ location.replace(github)
+
+ assert_equal github, window.url
+ assert_equal github, location.href
+
+ assert_equal google, location.history.first
+ assert_equal google, location.history.last
+ end
+
+ test "Location#toString: Returns the string representation of the Location object's URL" do
+ assert_equal google, location.toString
+ end
+
+ test "modifying the url's hash (fragment) loads the resulting url to the window" do
+ location.hash = '#foo'
+ assert_equal 'foo', URI.parse(window.url).fragment
+ end
+
+ test "modifying the url's host loads the resulting url to the window" do
+ location.host = 'github.com:3030'
+ assert_equal 'github.com', URI.parse(window.url).host
+ assert_equal 3030, URI.parse(window.url).port
+ end
+
+ test "modifying the url's hostname loads the resulting url to the window" do
+ location.hostname = 'github.com'
+ assert_equal 'github.com', URI.parse(window.url).host
+ end
+
+ test "modifying the url's href loads the resulting url to the window" do
+ url = 'http://github.com:8080/home?foo=bar#baz'
+ location.href = url
+ assert_equal url, window.url
+ end
+
+ test "modifying the url's pathname loads the resulting url to the window" do
+ location.pathname = 'home'
+ assert_equal '/home', URI.parse(window.url).path
+ end
+
+ test "modifying the url's port loads the resulting url to the window" do
+ location.port = '8080'
+ assert_equal 8080, URI.parse(window.url).port
+ end
+
+ test "modifying the url's protocol loads the resulting url to the window" do
+ location.protocol = 'https'
+ assert_equal 'https', URI.parse(window.url).scheme
+ end
+end
+
View
95 test/dom/window_test.rb
@@ -0,0 +1,95 @@
+require File.expand_path('../../test_helper', __FILE__)
+
+require 'webmock/test_unit'
+
+class WindowTest < Test::Unit::TestCase
+ include WebMock
+
+ attr_reader :window
+
+ def setup
+ @window = Taka::Window.new
+ window.location.instance_variable_set(:@uri, URI.parse('http://example.org'))
+ end
+
+ def jquery
+ File.open(File.expand_path('../jquery-1.4.2.js', __FILE__), 'r') { |f| f.read }
+ end
+
+ def stub_get(path, body)
+ stub_request(:any, "http://example.org/#{path}").to_return(:body => body)
+ end
+
+ test "load loads an html document" do
+ window.load('<html></html>')
+ assert_match /html/, window.document.to_s
+ end
+
+ test "load loads a file" do
+ window.load(File.expand_path('../../../README.rdoc', __FILE__))
+ assert_match /Taka/, window.document.to_s
+ end
+
+ test "loads linked scripts" do
+ stub_get('foo.js', 'document.title = "foo"')
+ window.load('<html><head><title></title><script src="/foo.js"></script></head></html>')
+ assert_equal 'foo', window.document.title
+ end
+
+ test "can load and use jquery" do
+ stub_get('jquery.js', jquery)
+ window.load <<-html
+ <html>
+ <head>
+ <script src="/jquery.js"></script>
+ <script>$(document).ready(function() { log($("body").length) })</script>
+ </head>
+ <body></body>
+ </html>
+ html
+ assert_equal 1, window.console.log.last.last
+ end
+
+ test "jquery selectors" do
+ stub_get('jquery.js', jquery)
+ window.load <<-html
+ <html>
+ <head><script src="/jquery.js"></script></head>
+ <body><div id="foo"><ol><li class="bar"></li></ol></div></body>
+ </html>
+ html
+ assert_equal 1, window.evaluate('$("div").length')
+ assert_equal 1, window.evaluate('$("#foo").length')
+ assert_equal 1, window.evaluate('$("#foo ol li").length')
+ assert_equal 1, window.evaluate('$(".bar").length')
+ # assert_equal 1, window.evaluate('$("html body #foo ol:nth-child(0) li.bar").length') # TODO!
+ end
+
+ test "jquery dom generation" do
+ stub_get('jquery.js', jquery)
+ window.load('<html><head><script src="/jquery.js"></script></head><body></body></html>')
+ html = window.evaluate('jQuery("<div/><hr/><code/><b/>").toArray()').join('')
+ assert_equal '<div></div><hr><code></code><b></b>', html
+ end
+
+ test "executes scripts" do
+ window.load('<html><head><title></title><script>document.title = "foo"</script></head></html>')
+ assert_equal 'foo', window.document.title
+ end
+
+ test "uri? returns true if the given argument is a (file or http) url, otherwise false" do
+ assert window.send(:uri?, 'http://google.com')
+ assert window.send(:uri?, 'file://tmp/foo.txt')
+
+ assert !window.send(:uri?, '/tmp/foo.txt')
+ assert !window.send(:uri?, '<html></html>')
+ end
+
+ test "file? returns true if the given argument is an absolute filename, otherwise false" do
+ assert window.send(:file?, '/tmp/foo.txt')
+
+ assert !window.send(:file?, 'file://tmp/foo.txt')
+ assert !window.send(:file?, 'http://google.com')
+ assert !window.send(:file?, '<html></html>')
+ end
+end
View
2 test/w3c-dom/level1/core/test_documentgetelementsbytagnametotallength.rb
@@ -53,10 +53,8 @@ def test_documentgetelementsbytagnametotallength
nameList = doc.getElementsByTagName("*")
if (("image/svg+xml" == getContentType()))
assertSize("elementCountSVG", 39, nameList)
-
else
assertSize("documentGetElementsByTagNameTotalLengthAssert", 37, nameList)
-
end
end
View
1 test/w3c_helper.rb
@@ -14,7 +14,6 @@
require 'johnson'
require File.expand_path('../known_issues.rb', __FILE__)
-require File.expand_path('../dom_test_case.rb', __FILE__)
module DOM
class TestCase < Test::Unit::TestCase

0 comments on commit b7ffe2c

Please sign in to comment.