Module: Vapir::ElementHelper

Includes:
ElementClassAndModuleMethods
Included in:
Area, Button, CheckBox, Dd, Div, Dl, Dt, Element, Em, FileField, Form, Frame, H1, H2, H3, H4, H5, H6, Hidden, Image, InputElement, Label, Li, Link, Map, Ol, Option, P, Pre, Radio, SelectList, Span, Strong, TBody, Table, TableCell, TableRow, TextField, Ul
Defined in:
lib/vapir-common/element_class_and_module.rb

Instance Method Summary collapse

Methods included from ElementClassAndModuleMethods

#add_container_method_extra_args, #all_dom_attr_aliases, #all_dom_attrs, #class_array_append, #class_array_get, #class_hash_get, #class_hash_merge, #container_collection_methods, #container_method_extra_args, #container_single_methods, #default_how, #dom_attr, #dom_attr_locate_alias, #dom_function, #dom_setter, #element_collection, #factory, #inspect_these, #inspect_this_if, #parent_element_module, #set_or_get_class_var, #specifiers

Instance Method Details

#add_specifier(specifier) ⇒ Object



239
240
241
# File 'lib/vapir-common/element_class_and_module.rb', line 239

def add_specifier(specifier)
  class_array_append 'specifiers', specifier
end

#container_collection_method(*method_names) ⇒ Object



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/vapir-common/element_class_and_module.rb', line 297

def container_collection_method(*method_names)
  class_array_append 'container_collection_methods', *method_names
  element_module=self
  method_names.each do |container_multiple_method|
    Vapir::Container.module_eval do
      # returns an ElementCollection of Elements that are instances of the including class 
      define_method(container_multiple_method) do |*args|
        case args.length
        when 0
          ElementCollection.new(self, element_class_for(element_module), extra_for_contained)
        when 1,2
          first, second=*args
          how, what, index= *normalize_how_what_index(first, second, element_class_for(element_module))
          if index
            raise ArgumentError, "Cannot specify index on collection method! specified index was #{index.inspect}"
          end
          ElementCollection.new(self, element_class_for(element_module), extra_for_contained, how, what)
        else
          raise ArgumentError, "wrong number of arguments - expected 0 arguments, 1 argument (hash of attributes), or 2 arguments ('how' and 'what'). got #{args.length}: #{args.inspect}"
        end
      end
      define_method('child_'+container_multiple_method.to_s) do
        ElementCollection.new(self, element_class_for(element_module), extra_for_contained.merge(:candidates => :childNodes))
      end
      define_method('show_'+container_multiple_method.to_s) do |*io|
        io=io.first||$stdout # io is a *array so that you don't have to give an arg (since procs don't do default args)
        element_collection=ElementCollection.new(self, element_class_for(element_module), extra_for_contained)
        io.write("There are #{element_collection.length} #{container_multiple_method}\n")
        element_collection.each do |element|
          io.write(element.to_s)
        end
      end
      alias_deprecated "show#{container_multiple_method.to_s.capitalize}", "show_"+container_multiple_method.to_s
    end
  end
end

#container_single_method(*method_names) ⇒ Object



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/vapir-common/element_class_and_module.rb', line 243

def container_single_method(*method_names)
  class_array_append 'container_single_methods', *method_names
  element_module=self
  method_names.each do |method_name|
    Vapir::Element.module_eval do
      # these methods (Element#parent_table, Element#parent_div, etc)
      # iterate through parent nodes looking for a parent of the specified
      # type. if no element of that type is found which is a parent of
      # self, returns nil. 
      define_method("parent_#{method_name}") do
        element_class=element_class_for(element_module)
        parentNode=element_object
        while true
          parentNode=parentNode.parentNode
          unless parentNode && parentNode != document_object # don't ascend up to the document. #TODO/Fix - for IE, comparing WIN32OLEs doesn't really work, this comparison is pointless. 
            return nil
          end
          matched=Vapir::ElementObjectCandidates.match_candidates([parentNode], element_class.specifiers, element_class.all_dom_attr_aliases)
          if matched.size > 0
            return element_class.new(:element_object, parentNode, extra_for_contained) # this is a little weird, passing extra_for_contained so that this is the container of its parent. 
          end
        end
      end
    end
    element_module = self
    # define both bang-methods (like #text_field!) and not (#text_field) with corresponding :locate option for element_by_howwhat
    [ {:method_name => method_name, :locate => true}, 
      {:method_name => method_name.to_s+'!', :locate => :assert},
      {:method_name => method_name.to_s+'?', :locate => :nil_unless_exists},
    ].each do |method_hash|
      Vapir::Container.module_eval do
        define_method(method_hash[:method_name]) do |*args| # can't take how, what as args because blocks don't do default values so it will want 2 args
          #locate! # make sure self is located before trying contained stuff 
          how=args.shift
          what=args.shift
          what_args=args
          other_attribute_keys=element_class_for(element_module).container_method_extra_args
          if what_args.size>other_attribute_keys.length
            raise ArgumentError, "\##{method_hash[:method_name]} takes 1 to #{2+other_attribute_keys.length} arguments! Got #{([how, what]+what_args).map{|a|a.inspect}.join(', ')}}"
          end
          if what_args.size == 0
            other_attributes= nil
          else
            other_attributes={}
            what_args.each_with_index do |arg, i|
              other_attributes[other_attribute_keys[i]]=arg
            end
          end
          element_by_howwhat(element_class_for(element_module), how, what, :locate => method_hash[:locate], :other_attributes => other_attributes)
        end
      end
    end
  end
end

#included(including_class) ⇒ Object



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/vapir-common/element_class_and_module.rb', line 336

def included(including_class)
  including_class.send :extend, ElementClassAndModuleMethods
  
  # copy constants (like Specifiers) onto classes when inherited
  # this is here to set the constants of the Element modules below onto the actual classes that instantiate 
  # per-browser (Vapir::IE::TextField, Vapir::Firefox::TextField, etc) so that calling #const_defined? on those 
  # returns true, and so that the constants defined here clobber any inherited stuff from superclasses
  # which is unwanted. 
  self.constants.each do |const| # copy all of its constants onto wherever it was included
    to_copy=self.const_get(const)
    to_copy=to_copy.dup if [Hash, Array, Set].any?{|klass| to_copy.is_a?(klass) }
    including_class.const_set(const, to_copy)
  end
  
  # now the constants (above) have switched away from constants to class variables, pretty much, so copy those.
  self.class_variables.each do |class_var|
    to_copy=class_variable_get(class_var)
    to_copy=to_copy.dup if [Hash, Array, Set].any?{|klass| to_copy.is_a?(klass) }
    including_class.send(:class_variable_set, class_var, to_copy)
  end
  
  class << including_class
    def attributes_to_inspect
      super_attrs=superclass.respond_to?(:attributes_to_inspect) ? superclass.attributes_to_inspect : []
      super_attrs + class_array_get('attributes_to_inspect')
    end
    def all_dom_attrs
      super_attrs=superclass.respond_to?(:all_dom_attrs) ? superclass.all_dom_attrs : []
      super_attrs + class_array_get('dom_attrs')
    end
    def all_dom_attr_aliases
      aliases=class_hash_get('dom_attr_aliases').dup
      super_aliases=superclass.respond_to?(:all_dom_attr_aliases) ? superclass.all_dom_attr_aliases : {}
      super_aliases.each_pair do |attr, alias_list|
        aliases[attr] = (aliases[attr] || Set.new) + alias_list
      end
      aliases
    end
  end
end