Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

JavaScript namespacing proposal: Difference between revisions

From MoodleDocs
(New page: The idea of JavaScript namespacing was raised during the developers meeting that occured on Tuesday 29th September 2009 and I think its a fantastic idea, so I wrote this wee proposal and p...)
 
(Marking this page as obsolete.)
(2 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{obsolete}}
The idea of JavaScript namespacing was raised during the developers meeting that occured on Tuesday 29th September 2009 and I think its a fantastic idea, so I wrote this wee proposal and plan to hopefully win people over and get this is in for Moodle 2.0.
The idea of JavaScript namespacing was raised during the developers meeting that occured on Tuesday 29th September 2009 and I think its a fantastic idea, so I wrote this wee proposal and plan to hopefully win people over and get this is in for Moodle 2.0.


Line 5: Line 6:
===Concept===
===Concept===
The concept is to apply a namespacing scheme to the JavaScript that is used by Moodle core code. By namespacing the JavaScript we can better define the structure of the JavaScript code as well as hopefully make it both more easily accessible and with any luck make it easier to develop JavaScript that is potentially reusable.
The concept is to apply a namespacing scheme to the JavaScript that is used by Moodle core code. By namespacing the JavaScript we can better define the structure of the JavaScript code as well as hopefully make it both more easily accessible and with any luck make it easier to develop JavaScript that is potentially reusable.
To answer a few quick questions about the process:
; How long would it take to namespace the JavaScript : It wouldn't take very long at all to go through and apply a namespacing scheme to the JavaScript once the structure has been decided upon. Once the JavaScript has been namespaced it would be a simple case of iterating through the files that make up Moodle and converting references to the original JavaScript functions to thier namespaced equivilants.
; Does all JavaScript have to be namespaced : No not at all. Initially only the core JavaScript files would be converted. After this it would be up to developers to namespace thier code should they choose to.... it would be the perfect opertunity to revise that legacy JavaScript ;)
; What about code that uses the old function calls? : All of the core uses should be converted as part of the task of namespacing however we certainly need to support the old function calls. We will create mapping functions that simply take a call to a non-namespaced function and pass it to its namespaced equivilant.
; Will any of the JavaScript change? : No. A couple of new internal functions will be introduced to support namespacing however the actual JavaScript functions being namespaced will not change. You will still be able to call them as you did before, you will just need to use the namespaced reference.
===Why bother?===
Because ....
# It greatly reduces the chances of developers accidentally creating clashing methods, or variables. Not just with core code but more importantly convlicts that may arrise between 3rd party extensions.
# Hopefully make the JavaScript code more usable and obvious by providing better organisation and structure. This will in turn hopefully reduce the number of identical functions that arise.
# It's the sort of thing that can only be done when revision of code is nessecary and there's no time like a major release for that.
# It looks better, more organised.


===The root namespace===
===The root namespace===
The root namespace at the moment I believe should be <strong>MOODLE</strong>. The reason for this is because it fits with the chosen JavaScript framework for Moodle, YUI. The version of YUI that Moodle has chosen to use is namespaced under <strong>YAHOO</strong> and whilst I realise that it appears that has been changed for the next major version (3.0) to just <strong>Y</strong> I personally think using MOODLE instead of something like M would be clearer to the development community.
After discussing this with the development team it was decided that the core namespace will be <strong>M</strong>. The original concept was to go with MOODLE however we decided that there was no need to go with the so many characters where one would do, and this fit in with the changes YUI was making in the release of version 3.0 changing their root namespace from <strong>YAHOO</strong> to <strong>Y</strong>.


===Core namespaces===
===Core namespaces===
The following are namspaces that will be created in order to support the initial conversion to a namespaced JavaScript core.
The following are namspaces that will be created in order to support the initial conversion to a namespaced JavaScript core.
; component : JavaScript that creates controls, or structures used throughout Moodle.
; control : JavaScript that creates controls, or structures used throughout Moodle.
; dom : JavaScript for interacting with the DOM.
; dom : JavaScript for interacting with the DOM.
; form : JavaScript for interacting with forms.
; form : JavaScript for interacting with forms.
; module : An empty namespace that gives 3rd party developers to extend in a safe area.
; util : Miscellaneous JavaScript functions.
; util : Miscelaneous JavaScript functions.
; user : JavaScript that is utilised in direct respect to the user.
; user : JavaScript that is utilised in direct respect to the user.
===Creating new namespaces===
Ideally additional code (or as it is being converted) should be namespaced directly after M with a name fitting to the PHP code. For modules this would be the module name e.g. M.forum .


===Time estimate===
===Time estimate===
Line 40: Line 26:


===Implementation===
===Implementation===
The implementation of the core namespace and supporting functions to further namespace is reasonably simple, however it would need to be the very first bit of Moodle javascript to be executed. This simply means it would be defined and set up within javascript-priority.js which is the first file to be included in the HTML head.
The implementation of the core namespace and supporting functions to further namespace is reasonably simple, however it would need to be the very first bit of Moodle JavaScript to be executed. This simply means it would be defined and set up within javascript-priority.js which is the first file to be included in the HTML head.


===Conversion of JavaScript files===
===Conversion of JavaScript files===
Line 51: Line 37:
|-
|-
| block_hider
| block_hider
| MOODLE.util.block_hider
| M.util.block_hider
| object
| object
|-
|-
| checkall
| checkall
| MOODLE.form.check_all
| M.form.check_all
| function
| function
|-
|-
| checknone
| checknone
| MOODLE.form.check_none
| M.form.check_none
| function
| function
|-
|-
| collapsible_region
| collapsible_region
| MOODLE.dom.collapsible_region
| M.dom.collapsible_region
| object
| object
|-
|-
| deselect_all_in
| deselect_all_in
| MOODLE.form.deselect_all_in
| M.form.deselect_all_in
| function
| function
|-
|-
| findParentNode
| findParentNode
| MOODLE.dom.find_parent
| M.dom.find_parent
| function
| function
|-
|-
| fix_column_width
| fix_column_width
| MOODLE.util.fix_column_width
| M.util.fix_column_width
| function
| function
|-
|-
| fix_column_widths
| fix_column_widths
| MOODLE.util.fix_column_widths
| M.util.fix_column_widths
| function
| function
|-
|-
| focuscontrol
| focuscontrol
| MOODLE.form.set_focus
| M.form.set_focus
| function
| function
|-
|-
| frame_breakout
| frame_breakout
| MOODLE.frame.add_breakout_target
| M.frame.add_breakout_target
| function
| function
|-
|-
| init_help_icons
| init_help_icons
| MOODLE.util.init_help_icons
| M.util.init_help_icons
| function
| function
|-
|-
| openpopup
| openpopup
| MOODLE.util.window.popup
| M.util.window.popup
| function
| function
|-
|-
| select_all_in
| select_all_in
| MOODLE.form.select_all_in
| M.form.select_all_in
| function
| function
|-
|-
| submit_form_by_id
| submit_form_by_id
| MOODLE.form.submit_form_by_id
| M.form.submit_form_by_id
| function
| function
|-
|-
| emoticons_help
| emoticons_help
| MOODLE.util.emoticons_help
| M.util.emoticons_help
| object
| object
|-
|-
Line 123: Line 109:
|-
|-
| build_querystring
| build_querystring
| MOODLE.util.build_query_string
| M.util.build_query_string
| function
| function
|-
|-
| cancel_scroll_to_end
| cancel_scroll_to_end
| MOODLE.util.scroll.cancel_autoscroll
| M.util.scroll.cancel_autoscroll
| function
| function
|-
|-
| close_window
| close_window
| MOODLE.util.window.close
| M.util.window.close
| function
| function
|-
|-
| close_window_reload
| close_window_reload
| MOODLE.util.window.reload_close
| M.util.window.reload_close
| function
| function
|-
|-
| confirm_dialog
| confirm_dialog
| MOODLE.component.confirmdialog
| M.control.confirmdialog
| object
| object
|-
|-
| create_UFO_object
| create_UFO_object
| MOODLE.component.ufo.create
| M.control.ufo.create
| function
| function
|-
|-
| destroy_item
| destroy_item
| MOODLE.dom.element.remove
| M.dom.element.remove
| function
| function
|-
|-
Line 155: Line 141:
|-
|-
| hide_item
| hide_item
| MOODLE.dom.element.hide
| M.dom.element.hide
| function
| function
|-
|-
| json_decode
| json_decode
| MOODLE.util.json.decode
| M.util.json.decode
| function
| function
|-
|-
| json_encode
| json_encode
| MOODLE.util.json.encode
| M.util.json.encode
| function
| function
|-
|-
| repeatedly_scroll_t
| repeatedly_scroll_t
| MOODLE.util.scroll.autoscroll
| M.util.scroll.autoscroll
| function
| function
|-
|-
| scroll_to_end
| scroll_to_end
| MOODLE.util.scroll.bottom
| M.util.scroll.bottom
| function
| function
|-
|-
|  
|  
| MOODLE.util.scroll.top
| M.util.scroll.top
| function
| function
|-
|-
| set_user_preference
| set_user_preference
| MOODLE.user.set_preference
| M.user.set_preference
| function
| function
|-
|-
| show_item
| show_item
| MOODLE.dom.element.show
| M.dom.element.show
| function
| function
|-
|-
| stripHTML
| stripHTML
| MOODLE.util.strip_html
| M.util.strip_html
| function
| function
|-
|-
| unmaskPassword
| unmaskPassword
| MOODLE.form.unmask_password
| M.form.unmask_password
| function
| function
|-
|-
| update_progress_bar
| update_progress_bar
| MOODLE.component.progressbar.update
| M.control.progressbar.update
| function
| function
|}
|}
Line 207: Line 193:
|-
|-
| create_shadow
| create_shadow
| MOODLE.component.shadow.create
| M.control.shadow.create
| function
| function
|-
|-
| move_all_sidetabs_t...
| move_all_sidetabs_t...
| MOODLE.component.dock.undock_all
| M.control.dock.undock_all
| function
| function
|-
|-
| navigation_tab_panel
| navigation_tab_panel
| MOODLE.component.dock
| M.control.dock
| object
| object
|-
|-
| navigation_tree
| navigation_tree
| MOODLE.component.tree
| M.control.tree
| object
| object
|-
|-
| navigation_tree_branch
| navigation_tree_branch
| MOODLE.component.tree.branch
| M.control.tree.branch
| object
| object
|-
|-
| remove_shadow
| remove_shadow
| MOODLE.component.shadow.remove
| M.control.shadow.remove
| function
| function
|-
|-
| setup_new_navtree
| setup_new_navtree
| MOODLE.component.tree.init
| M.control.tree.init
| function
| function
|}
|}
Line 243: Line 229:
|-
|-
| deprecate
| deprecate
| MOODLE.util.deprecate
| M.util.deprecate
| function
| function
|-
|-
| deprecated_addonload
| deprecated_addonload
| MOODLE.util.deprecated.addonload
| M.util.deprecated.addonload
| function
| function
|-
|-
| deprecated_confirm_if
| deprecated_confirm_if
| MOODLE.util.deprecated.confirm_if
| M.util.deprecated.confirm_if
| function
| function
|-
|-
| submitFormById
| submitFormById
| MOODLE.util.deprecated.submitFormById
| M.util.deprecated.submitFormById
| function
| function
|}
|}
Line 267: Line 253:
|-
|-
| date_selector_calendar
| date_selector_calendar
| MOODLE.form.mforms.date_selector.calendar
| M.form.mforms.date_selector.calendar
| object
| object
|-
|-
| elementShowAdvanced
| elementShowAdvanced
| MOODLE.form.mforms.show_advanced.show
| M.form.mforms.show_advanced.show
| function
| function
|-
|-
| get_form_element_value
| get_form_element_value
| MOODLE.form.mforms.get_element_value
| M.form.mforms.get_element_value
| function
| function
|-
|-
| init_date_selectors
| init_date_selectors
| MOODLE.form.mforms.date_selector.init
| M.form.mforms.date_selector.init
| function
| function
|-
|-
| lockoptionsall
| lockoptionsall
| MOODLE.form.mforms.lockoptionsall
| M.form.mforms.lockoptionsall
| function
| function
|-
|-
| lockoptionsallsetup
| lockoptionsallsetup
| MOODLE.form.mforms.lockoptionsallsetup
| M.form.mforms.lockoptionsallsetup
| function
| function
|-
|-
| set_form_element_disabled
| set_form_element_disabled
| MOODLE.form.mforms.disable_element
| M.form.mforms.disable_element
| funciton
| funciton
|-
|-
| showAdvancedInit
| showAdvancedInit
| MOODLE.form.mforms.show_advanced.init
| M.form.mforms.show_advanced.init
| function
| function
|-
|-
| showAdvancedOnClick
| showAdvancedOnClick
| MOODLE.form.mforms.show_advanced.handle_click
| M.form.mforms.show_advanced.handle_click
| function
| function
|}
|}


===Resulting namespaced structure===
===Resulting namespaced structure===
*<strong>MOODLE</strong>
*<strong>M</strong>
**<strong>component</strong>
**<strong>control</strong>
***<em>confirmdialog</em>
***<em>confirmdialog</em>
***<em>dock</em>
***<em>dock</em>
Line 371: Line 357:
**<strong>user</strong>
**<strong>user</strong>
***set_preference
***set_preference
===Why bother?===
Because ....
# It greatly reduces the chances of developers accidentally creating clashing methods, or variables. Not just with core code but more importantly conflicts that may arise between 3rd party extensions.
# Hopefully make the JavaScript code more usable and obvious by providing better organisation and structure. This will in turn hopefully reduce the number of identical functions that arise.
# It's the sort of thing that can only be done when revision of code is necessary and there's no time like a major release for that.
# It looks better, more organised.
===Questions===
To answer a few quick questions about the process:
; How long would it take to namespace the JavaScript : It wouldn't take very long at all to go through and apply a namespacing scheme to the JavaScript once the structure has been decided upon. Once the JavaScript has been namespaced it would be a simple case of iterating through the files that make up Moodle and converting references to the original JavaScript functions to their namespaced equivalents.
; Does all JavaScript have to be namespaced : No not at all. Initially only the core JavaScript files would be converted. After this it would be up to developers to namespace their code should they choose to.... it would be the perfect opportunity to revise that legacy JavaScript ;)
; What about code that uses the old function calls? : All of the core uses should be converted as part of the task of namespacing however we certainly need to support the old function calls. We will create mapping functions that simply take a call to a non-namespaced function and pass it to its namespaced equivalent.
; Will any of the JavaScript change? : No. A couple of new internal functions will be introduced to support namespacing however the actual JavaScript functions being namespaced will not change. You will still be able to call them as you did before, you will just need to use the namespaced reference.

Revision as of 20:35, 24 March 2013

Warning: This page is no longer in use. The information contained on the page should NOT be seen as relevant or reliable.

The idea of JavaScript namespacing was raised during the developers meeting that occured on Tuesday 29th September 2009 and I think its a fantastic idea, so I wrote this wee proposal and plan to hopefully win people over and get this is in for Moodle 2.0.

Note: This proposal assumes that the patch proposed for MDL-16699 that splits javascript-static into two files and moves JavaScript that is only being used in a single place within Moodle to a file that can be included by the code that uses it.

Concept

The concept is to apply a namespacing scheme to the JavaScript that is used by Moodle core code. By namespacing the JavaScript we can better define the structure of the JavaScript code as well as hopefully make it both more easily accessible and with any luck make it easier to develop JavaScript that is potentially reusable.

The root namespace

After discussing this with the development team it was decided that the core namespace will be M. The original concept was to go with MOODLE however we decided that there was no need to go with the so many characters where one would do, and this fit in with the changes YUI was making in the release of version 3.0 changing their root namespace from YAHOO to Y.

Core namespaces

The following are namspaces that will be created in order to support the initial conversion to a namespaced JavaScript core.

control
JavaScript that creates controls, or structures used throughout Moodle.
dom
JavaScript for interacting with the DOM.
form
JavaScript for interacting with forms.
util
Miscellaneous JavaScript functions.
user
JavaScript that is utilised in direct respect to the user.

Creating new namespaces

Ideally additional code (or as it is being converted) should be namespaced directly after M with a name fitting to the PHP code. For modules this would be the module name e.g. M.forum .

Time estimate

I think it would take a day to namespace the JavaScript files, and then a further day or two to convert the function calls and test. It is a reasonably simple procedure and with all of the JavaScript clean up that has gone into head already there should be realivily few edge cases left.

Implementation

The implementation of the core namespace and supporting functions to further namespace is reasonably simple, however it would need to be the very first bit of Moodle JavaScript to be executed. This simply means it would be defined and set up within javascript-priority.js which is the first file to be included in the HTML head.

Conversion of JavaScript files

lib/javascript-static.js

Declaration Namespaced declaration Declaration type
block_hider M.util.block_hider object
checkall M.form.check_all function
checknone M.form.check_none function
collapsible_region M.dom.collapsible_region object
deselect_all_in M.form.deselect_all_in function
findParentNode M.dom.find_parent function
fix_column_width M.util.fix_column_width function
fix_column_widths M.util.fix_column_widths function
focuscontrol M.form.set_focus function
frame_breakout M.frame.add_breakout_target function
init_help_icons M.util.init_help_icons function
openpopup M.util.window.popup function
select_all_in M.form.select_all_in function
submit_form_by_id M.form.submit_form_by_id function
emoticons_help M.util.emoticons_help object
old_onload_focus To be depreacted as part of MDL-19740

lib/javascript-priority.js

Declaration Namespaced declaration Declaration type
build_querystring M.util.build_query_string function
cancel_scroll_to_end M.util.scroll.cancel_autoscroll function
close_window M.util.window.close function
close_window_reload M.util.window.reload_close function
confirm_dialog M.control.confirmdialog object
create_UFO_object M.control.ufo.create function
destroy_item M.dom.element.remove function
getElementsByClassName Should really be deprecated in favour of YUI equivilant
hide_item M.dom.element.hide function
json_decode M.util.json.decode function
json_encode M.util.json.encode function
repeatedly_scroll_t M.util.scroll.autoscroll function
scroll_to_end M.util.scroll.bottom function
M.util.scroll.top function
set_user_preference M.user.set_preference function
show_item M.dom.element.show function
stripHTML M.util.strip_html function
unmaskPassword M.form.unmask_password function
update_progress_bar M.control.progressbar.update function

lib/javascript-navigation.js

Declaration Namespaced declaration Declaration type
create_shadow M.control.shadow.create function
move_all_sidetabs_t... M.control.dock.undock_all function
navigation_tab_panel M.control.dock object
navigation_tree M.control.tree object
navigation_tree_branch M.control.tree.branch object
remove_shadow M.control.shadow.remove function
setup_new_navtree M.control.tree.init function

lib/javascript-deprecated.js

Declaration Namespaced declaration Declaration type
deprecate M.util.deprecate function
deprecated_addonload M.util.deprecated.addonload function
deprecated_confirm_if M.util.deprecated.confirm_if function
submitFormById M.util.deprecated.submitFormById function

lib/form/form.js

Declaration Namespaced declaration Declaration type
date_selector_calendar M.form.mforms.date_selector.calendar object
elementShowAdvanced M.form.mforms.show_advanced.show function
get_form_element_value M.form.mforms.get_element_value function
init_date_selectors M.form.mforms.date_selector.init function
lockoptionsall M.form.mforms.lockoptionsall function
lockoptionsallsetup M.form.mforms.lockoptionsallsetup function
set_form_element_disabled M.form.mforms.disable_element funciton
showAdvancedInit M.form.mforms.show_advanced.init function
showAdvancedOnClick M.form.mforms.show_advanced.handle_click function

Resulting namespaced structure

  • M
    • control
      • confirmdialog
      • dock
        • undock_all
      • tree
        • branch
      • progressbar
        • update
      • shadow
        • create
        • remove
      • ufo
        • create
    • dom
      • element
        • hide
        • remove
        • show
      • collapsible_region
      • find_parent
    • form
      • mforms
        • date_selector
          • calendar
          • init
        • show_advanced
          • init
          • handle_click
          • show
        • get_element_value
        • lockoptionsall
        • lockoptionsallsetup
        • disable_element
      • check_all
      • check_none
      • deselect_all_in
      • set_focus
      • select_all_in
      • submit_form_by_id
      • unmask_password
    • util
      • deprecated
        • addonload
        • confirm_if
        • submitFormById
      • json
        • decode
        • encode
      • scroll
        • autoscroll
        • bottom
        • top
      • window
        • close
        • popup
        • reload_close
      • block_hider
      • fix_column_width
      • fix_column_widths
      • init_help_icons
      • emoticons_help
      • build_query_string
      • strip_html
      • deprecate
    • user
      • set_preference

Why bother?

Because ....

  1. It greatly reduces the chances of developers accidentally creating clashing methods, or variables. Not just with core code but more importantly conflicts that may arise between 3rd party extensions.
  2. Hopefully make the JavaScript code more usable and obvious by providing better organisation and structure. This will in turn hopefully reduce the number of identical functions that arise.
  3. It's the sort of thing that can only be done when revision of code is necessary and there's no time like a major release for that.
  4. It looks better, more organised.

Questions

To answer a few quick questions about the process:

How long would it take to namespace the JavaScript
It wouldn't take very long at all to go through and apply a namespacing scheme to the JavaScript once the structure has been decided upon. Once the JavaScript has been namespaced it would be a simple case of iterating through the files that make up Moodle and converting references to the original JavaScript functions to their namespaced equivalents.
Does all JavaScript have to be namespaced
No not at all. Initially only the core JavaScript files would be converted. After this it would be up to developers to namespace their code should they choose to.... it would be the perfect opportunity to revise that legacy JavaScript ;)
What about code that uses the old function calls?
All of the core uses should be converted as part of the task of namespacing however we certainly need to support the old function calls. We will create mapping functions that simply take a call to a non-namespaced function and pass it to its namespaced equivalent.
Will any of the JavaScript change?
No. A couple of new internal functions will be introduced to support namespacing however the actual JavaScript functions being namespaced will not change. You will still be able to call them as you did before, you will just need to use the namespaced reference.