Class: Netzke::Core::ClientClassConfig

Inherits:
Object
  • Object
show all
Defined in:
lib/netzke/core/client_class_config.rb

Overview

This class is responsible of creation of the client (JavaScript) class. It is passed as block parameter to the `client_class` DSL method:

class MyComponent < Netzke::Base
  client_class do |c|
    c.extend = "Ext.form.Panel"
  end
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(klass, called_from) ⇒ ClientClassConfig

Returns a new instance of ClientClassConfig



13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/netzke/core/client_class_config.rb', line 13

def initialize(klass, called_from)
  @klass = klass
  @called_from = @dir = called_from
  @requires_as_string = ""
  @explicit_override_paths = []
  @properties = {
    extend: extended_class,
    alias: class_alias,
  }
  @properties[:mixins] = ['Netzke.Base'] if extending_extjs_component?
  @translated_properties = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

Allows assigning JavaScript prototype properties, including functions:

class MyComponent < Netzke::Base
  client_class do |c|
    # this will result in the +title+ property defined on the client class prototype
    c.title = "My cool component"

    # this will result in the +onButtonPress+ function defined on the client class prototype
    c.on_button_press = l("function(){\n// ...\n}\n")
  end
end

An better way to define prototype properties though is by using #include

As attributes are accessible from inside client_class:

class MyComponent < Netzke::Base
  class_attribute :title
  self.title = "Some default title"
  client_class do |c|
    c.title = self.title
  end
end

…you can configure your component on a class level like this:

# e.g. in Rails initializers
MyComponent.title = "New title for all MyComponents"

Or using a helper method provided by Netzke:

MyComponent.setup do |config|
  config.title = "New title for all MyComponents"
end


64
65
66
67
68
69
70
71
# File 'lib/netzke/core/client_class_config.rb', line 64

def method_missing(name, *args)
  if name =~ /(.+)=$/
    value = args.first
    @properties[$1.to_sym] = value
  else
    @properties[name.to_sym]
  end
end

Instance Attribute Details

#base_classObject

Returns the value of attribute base_class



11
12
13
# File 'lib/netzke/core/client_class_config.rb', line 11

def base_class
  @base_class
end

#dirObject

Returns the value of attribute dir



11
12
13
# File 'lib/netzke/core/client_class_config.rb', line 11

def dir
  @dir
end

#propertiesObject

Returns the value of attribute properties



11
12
13
# File 'lib/netzke/core/client_class_config.rb', line 11

def properties
  @properties
end

#requires_as_stringObject

Returns the value of attribute requires_as_string



11
12
13
# File 'lib/netzke/core/client_class_config.rb', line 11

def requires_as_string
  @requires_as_string
end

#translated_propertiesObject

Returns the value of attribute translated_properties



11
12
13
# File 'lib/netzke/core/client_class_config.rb', line 11

def translated_properties
  @translated_properties
end

Instance Method Details

#alias_prefixObject

Alias prefix: 'widget' for components, 'plugin' for plugins



212
213
214
# File 'lib/netzke/core/client_class_config.rb', line 212

def alias_prefix
  @klass < Netzke::Plugin ? "plugin" : "widget"
end

#class_aliasObject

The alias, required by Ext.Component, e.g.: widget.helloworld



150
151
152
# File 'lib/netzke/core/client_class_config.rb', line 150

def class_alias
  [alias_prefix, xtype].join(".")
end

#class_codeObject

Component's JavaScript class declaration. It gets stored in the JS class cache storage (Netzke.cache) at the client side to be reused at the moment of component instantiation.



162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/netzke/core/client_class_config.rb', line 162

def class_code
  res = []
  # Defining the scope if it isn't known yet
  res << %{Ext.ns("#{scope}");} unless scope == default_scope

  res << class_declaration

  # Store created class xtype in the cache
  res << %(
Netzke.cache.push('#{xtype}');
)

  res.join("\n")
end

#class_declarationObject

Generates declaration of the JS class as direct extension of a Ext component



205
206
207
208
209
# File 'lib/netzke/core/client_class_config.rb', line 205

def class_declaration
%(Ext.define('#{class_name}', #{properties_as_string});

#{overrides_as_string})
end

#class_nameObject

Returns the full name of the JavaScript class, including the scopes and the common scope, which is 'Netzke'. E.g.: “Netzke.Basepack.GridPanel”



190
191
192
# File 'lib/netzke/core/client_class_config.rb', line 190

def class_name
  [scope.presence, @klass.name.split("::").last].compact.join(".")
end

#code_with_dependenciesObject

JavaScript code needed for this particulaer class. Includes external JS code and the JS class definition for self.



200
201
202
# File 'lib/netzke/core/client_class_config.rb', line 200

def code_with_dependencies
  [requires_as_string, class_code].join("\n")
end

#default_scopeObject

Additional scope for your Netzke components.



178
179
180
# File 'lib/netzke/core/client_class_config.rb', line 178

def default_scope
  ""
end

#expand_client_code_path(ref) ⇒ Object



225
226
227
# File 'lib/netzke/core/client_class_config.rb', line 225

def expand_client_code_path(ref)
  "#{@dir}/client/#{ref}.js"
end

#extended_classObject

Default extended class



221
222
223
# File 'lib/netzke/core/client_class_config.rb', line 221

def extended_class
  extending_extjs_component? ? "Ext.panel.Panel" : @klass.superclass.client_class_config.class_name
end

#extending_extjs_component?Boolean

Whether we have to inherit from an Ext JS component, or a Netzke component

Returns:

  • (Boolean)


195
196
197
# File 'lib/netzke/core/client_class_config.rb', line 195

def extending_extjs_component?
  @klass.superclass == Netzke::Base
end

#include(*refs) ⇒ Object

Use it to “include” JavaScript methods defined in a separate file. Behind the scenes it uses `Ext.Class.override` It may accept one or more symbols or strings.

Symbols will be expanded following a convention, e.g.:

class MyComponent < Netzke::Base
  client_class do |c|
    c.include :some_functionality
    #...
  end
end

This will “include” a JavaScript object defined in the file named {component_location}/my_component/client/some_functionality.js, which way contain something like this:

{
  someProperty: 100,
  someMethod: function(params){
    // ...
  }
}

Strings will be interpreted as a full path to the “included” file (useful for sharing client code between components).

Also, see defining JavaScript prototype properties with #method_missing.

Raises:

  • (ArgumentError)


122
123
124
125
126
127
128
# File 'lib/netzke/core/client_class_config.rb', line 122

def include(*refs)
  raise(ArgumentError, "wrong number of arguments (0 for 1 or more)") if refs.empty?

  refs.each do |ref|
    @explicit_override_paths << normalize_filepath(ref)
  end
end

#override_pathsObject



229
230
231
232
233
234
235
236
237
# File 'lib/netzke/core/client_class_config.rb', line 229

def override_paths
  return @override_paths if @override_paths

  @override_paths = @explicit_override_paths
  @dir = @called_from
  default_override_path = expand_client_code_path(@dir.split("/").last)
  @override_paths.prepend(default_override_path) if File.exist?(default_override_path)
  @override_paths
end

#overrides_as_stringObject



239
240
241
# File 'lib/netzke/core/client_class_config.rb', line 239

def overrides_as_string
  override_paths.map { |path| override_from_file(path) }.join("\n\n")
end

#properties_as_stringObject



216
217
218
# File 'lib/netzke/core/client_class_config.rb', line 216

def properties_as_string
  [properties.netzke_jsonify.to_json.chop].compact.join(",\n") + "}"
end

#require(*refs) ⇒ Object

Use it to specify JavaScript files to be loaded before this component's JavaScript code. Useful when using external extensions required by this component.

It may accept one or more symbols or strings.

Symbols will be expanded following a convention, e.g.:

class MyComponent < Netzke::Base
  client_class do |c|
    c.require :some_library
  end
end

This will “require” a JavaScript file {component_location}/my_component/client/some_library.js

Strings will be interpreted as full paths to the required JavaScript file:

client_class do |c|
  c.require "#{File.dirname(__FILE__)}/my_component/one.js", "#{File.dirname(__FILE__)}/my_component/two.js"
end

Raises:

  • (ArgumentError)


92
93
94
95
96
97
# File 'lib/netzke/core/client_class_config.rb', line 92

def require(*refs)
  raise(ArgumentError, "wrong number of arguments (0 for 1 or more)") if refs.empty?
  refs.each do |ref|
    @requires_as_string << require_from_file(normalize_filepath(ref))
  end
end

#scopeObject

Returns the scope of this component e.g. “Netzke.Basepack”



184
185
186
# File 'lib/netzke/core/client_class_config.rb', line 184

def scope
  [default_scope.presence, *@klass.name.split("::")[0..-2]].compact.join(".")
end

#translate(*args) ⇒ Object

Defines the “i18n” config property, that is a translation object for this component, such as:

i18n: {
  overwriteConfirm: "Are you sure you want to overwrite preset '{0}'?",
  overwriteConfirmTitle: "Overwriting preset",
  deleteConfirm: "Are you sure you want to delete preset '{0}'?",
  deleteConfirmTitle: "Deleting preset"
}

E.g.:

class MyComponent < Netzke::Base
  client_class do |c|
    c.translate :overwrite_confirm, :overwrite_confirm_title, :delete_confirm, :delete_confirm_title
  end
end


145
146
147
# File 'lib/netzke/core/client_class_config.rb', line 145

def translate(*args)
  @translated_properties |= args
end

#xtypeObject

Builds this component's xtype E.g.: netzkebasepackwindow, netzkebasepackgridpanel



156
157
158
# File 'lib/netzke/core/client_class_config.rb', line 156

def xtype
  @klass.name.gsub("::", "").downcase
end