--- /dev/null
+module Ym4r\r
+ module GmPlugin\r
+ #The module where all the Ruby-to-JavaScript conversion takes place. It is included by all the classes in the YM4R library.\r
+ module MappingObject\r
+ #The name of the variable in JavaScript space.\r
+ attr_reader :variable\r
+ \r
+ #Creates javascript code for missing methods + takes care of listeners\r
+ def method_missing(name,*args)\r
+ str_name = name.to_s\r
+ if str_name =~ /^on_(.*)/\r
+ if args.length != 1\r
+ raise ArgumentError("Only 1 argument is allowed on on_ methods");\r
+ else\r
+ Variable.new("GEvent.addListener(#{to_javascript},\"#{MappingObject.javascriptify_method($1)}\",#{args[0]})")\r
+ end\r
+ else\r
+ args.collect! do |arg|\r
+ MappingObject.javascriptify_variable(arg)\r
+ end\r
+ Variable.new("#{to_javascript}.#{MappingObject.javascriptify_method(str_name)}(#{args.join(",")})")\r
+ end\r
+ end\r
+ \r
+ #Creates javascript code for array or hash indexing\r
+ def [](index) #index could be an integer or string\r
+ return Variable.new("#{to_javascript}[#{MappingObject.javascriptify_variable(index)}]")\r
+ end\r
+\r
+ #Transforms a Ruby object into a JavaScript string : MAppingObject, String, Array, Hash and general case (using to_s)\r
+ def self.javascriptify_variable(arg)\r
+ if arg.is_a?(MappingObject)\r
+ arg.to_javascript\r
+ elsif arg.is_a?(String)\r
+ "\"#{MappingObject.escape_javascript(arg)}\""\r
+ elsif arg.is_a?(Array)\r
+ "[" + arg.collect{ |a| MappingObject.javascriptify_variable(a)}.join(",") + "]"\r
+ elsif arg.is_a?(Hash)\r
+ "{" + arg.to_a.collect do |v|\r
+ "#{MappingObject.javascriptify_method(v[0].to_s)} : #{MappingObject.javascriptify_variable(v[1])}"\r
+ end.join(",") + "}"\r
+ elsif arg.nil?\r
+ "undefined"\r
+ else\r
+ arg.to_s\r
+ end\r
+ end\r
+ \r
+ #Escape string to be used in JavaScript. Lifted from rails.\r
+ def self.escape_javascript(javascript)\r
+ javascript.gsub(/\r\n|\n|\r/, "\\n").gsub("\"") { |m| "\\#{m}" }\r
+ end\r
+ \r
+ #Transform a ruby-type method name (like add_overlay) to a JavaScript-style one (like addOverlay).\r
+ def self.javascriptify_method(method_name)\r
+ method_name.gsub(/_(\w)/){|s| $1.upcase}\r
+ end\r
+ \r
+ #Declares a Mapping Object bound to a JavaScript variable of name +variable+.\r
+ def declare(variable)\r
+ @variable = variable\r
+ "var #{@variable} = #{create};"\r
+ end\r
+\r
+ #declare with a random variable name\r
+ def declare_random(init,size = 8)\r
+ s = init.clone\r
+ 6.times { s << (i = Kernel.rand(62); i += ((i < 10) ? 48 : ((i < 36) ? 55 : 61 ))).chr }\r
+ declare(s)\r
+ end\r
+\r
+ #Checks if the MappinObject has been declared\r
+ def declared?\r
+ !@variable.nil?\r
+ end\r
+ \r
+ #Binds a Mapping object to a previously declared JavaScript variable of name +variable+.\r
+ def assign_to(variable)\r
+ @variable = variable\r
+ "#{@variable} = #{create};"\r
+ end\r
+\r
+ #Assign the +value+ to the +property+ of the MappingObject\r
+ def set_property(property, value)\r
+ "#{to_javascript}.#{MappingObject.javascriptify_method(property.to_s)} = #{MappingObject.javascriptify_variable(value)}"\r
+ end\r
+\r
+ #Returns the code to get a +property+ from the MappingObject\r
+ def get_property(property)\r
+ Variable.new("#{to_javascript}.#{MappingObject.javascriptify_method(property.to_s)}")\r
+ end\r
+ \r
+ #Returns a Javascript code representing the object\r
+ def to_javascript\r
+ unless @variable.nil?\r
+ @variable\r
+ else\r
+ create\r
+ end\r
+ end\r
+ \r
+ #Creates a Mapping Object in JavaScript.\r
+ #To be implemented by subclasses if needed\r
+ def create\r
+ end\r
+ end\r
+\r
+ #Used to bind a ruby variable to an already existing JavaScript one. It doesn't have to be a variable in the sense "var variable" but it can be any valid JavaScript expression that has a value.\r
+ class Variable\r
+ include MappingObject\r
+ \r
+ def initialize(variable)\r
+ @variable = variable\r
+ end\r
+ #Returns the javascript expression contained in the object.\r
+ def create\r
+ @variable\r
+ end\r
+ #Returns the expression inside the Variable followed by a ";"\r
+ def to_s\r
+ @variable + ";"\r
+ end\r
+\r
+ UNDEFINED = Variable.new("undefined")\r
+ end\r
+ end\r
+end\r
+\r