bacuview 1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. data/AUTHORS +2 -0
  2. data/ChangeLog +454 -0
  3. data/README.bacuview +7 -0
  4. data/README.rails +153 -0
  5. data/Rakefile +94 -0
  6. data/app/controllers/application.rb +11 -0
  7. data/app/controllers/client_controller.rb +27 -0
  8. data/app/controllers/job_controller.rb +100 -0
  9. data/app/controllers/jobmedia_controller.rb +2 -0
  10. data/app/controllers/media_controller.rb +44 -0
  11. data/app/controllers/misc_controller.rb +14 -0
  12. data/app/controllers/pool_controller.rb +38 -0
  13. data/app/helpers/application_helper.rb +88 -0
  14. data/app/helpers/client_finder.rb +112 -0
  15. data/app/helpers/client_helper.rb +45 -0
  16. data/app/helpers/job_helper.rb +56 -0
  17. data/app/helpers/jobmedia_helper.rb +2 -0
  18. data/app/helpers/media_helper.rb +14 -0
  19. data/app/helpers/misc_helper.rb +15 -0
  20. data/app/helpers/pool_helper.rb +2 -0
  21. data/app/models/client.rb +14 -0
  22. data/app/models/job.rb +21 -0
  23. data/app/models/jobmedia.rb +9 -0
  24. data/app/models/media.rb +23 -0
  25. data/app/models/pool.rb +13 -0
  26. data/app/views/client/_spec.rhtml +1 -0
  27. data/app/views/client/check.rhtml +1 -0
  28. data/app/views/client/index.rhtml +27 -0
  29. data/app/views/client/show.rhtml +8 -0
  30. data/app/views/job/_spec.rhtml +7 -0
  31. data/app/views/job/index.rhtml +38 -0
  32. data/app/views/job/last.rhtml +52 -0
  33. data/app/views/job/show.rhtml +19 -0
  34. data/app/views/job/spec.rhtml +38 -0
  35. data/app/views/layouts/bacuview-layout.rhtml +50 -0
  36. data/app/views/media/_spec.rhtml +1 -0
  37. data/app/views/media/index.rhtml +30 -0
  38. data/app/views/media/show.rhtml +8 -0
  39. data/app/views/misc/about.rhtml +2 -0
  40. data/app/views/misc/help.rhtml +1 -0
  41. data/app/views/pool/_spec.rhtml +1 -0
  42. data/app/views/pool/index.rhtml +29 -0
  43. data/app/views/pool/show.rhtml +8 -0
  44. data/bin/bacuview +3 -0
  45. data/config/bacuview.yml.template +2 -0
  46. data/config/boot.rb +19 -0
  47. data/config/database.yml.template +13 -0
  48. data/config/environment.rb +87 -0
  49. data/config/environments/development.rb +19 -0
  50. data/config/environments/production.rb +19 -0
  51. data/config/environments/test.rb +19 -0
  52. data/config/routes.rb +61 -0
  53. data/log/development.log +0 -0
  54. data/log/production.log +0 -0
  55. data/log/test.log +0 -0
  56. data/public/404.html +8 -0
  57. data/public/500.html +8 -0
  58. data/public/bacu-bat.png +0 -0
  59. data/public/bacuweb.css +7 -0
  60. data/public/client-sophie-thumb.png +0 -0
  61. data/public/client-sophie.png +0 -0
  62. data/public/clients-thumb.png +0 -0
  63. data/public/clients.png +0 -0
  64. data/public/dispatch.cgi +10 -0
  65. data/public/dispatch.fcgi +24 -0
  66. data/public/dispatch.rb +10 -0
  67. data/public/favicon.ico +0 -0
  68. data/public/home.html +108 -0
  69. data/public/images/bacu-bat.png +0 -0
  70. data/public/images/busy.png +0 -0
  71. data/public/images/dunno.png +0 -0
  72. data/public/images/error.png +0 -0
  73. data/public/images/okay.png +0 -0
  74. data/public/images/pool_pie.png +0 -0
  75. data/public/install.html +156 -0
  76. data/public/javascripts/application.js +2 -0
  77. data/public/javascripts/client_check.js +24 -0
  78. data/public/javascripts/controls.js +815 -0
  79. data/public/javascripts/dragdrop.js +724 -0
  80. data/public/javascripts/effects.js +953 -0
  81. data/public/javascripts/prototype.js +1985 -0
  82. data/public/job-1449-thumb.png +0 -0
  83. data/public/job-1449.png +0 -0
  84. data/public/job-last-thumb.png +0 -0
  85. data/public/job-last.png +0 -0
  86. data/public/jobs-thumb.png +0 -0
  87. data/public/jobs.png +0 -0
  88. data/public/media-39-thumb.png +0 -0
  89. data/public/media-39.png +0 -0
  90. data/public/media-thumb.png +0 -0
  91. data/public/media.png +0 -0
  92. data/public/news.html +144 -0
  93. data/public/pool-lto3-thumb.png +0 -0
  94. data/public/pool-lto3.png +0 -0
  95. data/public/pools-thumb.png +0 -0
  96. data/public/pools.png +0 -0
  97. data/public/robots.txt +1 -0
  98. data/public/stylesheets/bacuview.css +37 -0
  99. data/script/about +3 -0
  100. data/script/breakpointer +3 -0
  101. data/script/console +3 -0
  102. data/script/destroy +3 -0
  103. data/script/generate +3 -0
  104. data/script/performance/benchmarker +3 -0
  105. data/script/performance/profiler +3 -0
  106. data/script/plugin +3 -0
  107. data/script/process/reaper +3 -0
  108. data/script/process/spawner +3 -0
  109. data/script/process/spinner +3 -0
  110. data/script/runner +3 -0
  111. data/script/server +3 -0
  112. metadata +168 -0
data/config/routes.rb ADDED
@@ -0,0 +1,61 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ # Add your own custom routes here.
3
+ # The priority is based upon order of creation:
4
+ # first created -> highest priority.
5
+
6
+ # Here's a sample route:
7
+ # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
8
+ # Keep in mind you can assign values other than :controller and :action
9
+
10
+ # You can have the root of your site routed by hooking up ''
11
+ # -- just remember to delete public/index.html.
12
+ # map.connect '', :controller => "welcome"
13
+
14
+ map.connect '', :controller => "job", :action => "index",
15
+ :name => '0', :days => '1', :jsort => 'id'
16
+
17
+ # job route
18
+ map.connect 'job/last/:name',
19
+ :controller => 'job', :action => 'last'
20
+ map.connect 'job/show/:jid',
21
+ :controller => 'job', :action => 'show'
22
+ map.connect 'job/:name/:days/:jsort',
23
+ :controller => 'job', :action => 'index',
24
+ :name => '0', :days => '1', :jsort => 'id',
25
+ :requirements => { :jsort => /.*/ }
26
+
27
+ # client route
28
+ map.connect 'client/show/:cid',
29
+ :controller => 'client', :action => 'show'
30
+ map.connect 'client/check',
31
+ :controller => 'client', :action => 'check'
32
+ map.connect 'client/:csort',
33
+ :controller => 'client', :action => 'index', :csort => 'name',
34
+ :requirements => { :csort => /.*/ }
35
+
36
+ # pool route
37
+ map.connect 'pool/show/:pid',
38
+ :controller => 'pool', :action => 'show'
39
+ map.connect 'pool/dist/:psort',
40
+ :controller => 'pool', :action => 'dist', :psort => 'name'
41
+ map.connect 'pool/:psort',
42
+ :controller => 'pool', :action => 'index', :psort => 'name',
43
+ :requirements => { :psort => /.*/ }
44
+
45
+ # media route
46
+ map.connect 'media/show/:mid',
47
+ :controller => 'media', :action => 'show'
48
+ map.connect 'media/:msort',
49
+ :controller => 'media', :action => 'index', :msort => 'name',
50
+ :requirements => { :msort => /.*/ }
51
+ # misc routes
52
+ map.connect "about", :controller => 'misc', :action => 'about'
53
+ map.connect "help", :controller => 'misc', :action => 'help'
54
+
55
+ # Allow downloading Web Service WSDL as a file with an extension
56
+ # instead of a file named 'wsdl'
57
+ map.connect ':controller/service.wsdl', :action => 'wsdl'
58
+
59
+ # Install the default route as the lowest priority.
60
+ map.connect ':controller/:action/:id'
61
+ end
File without changes
File without changes
data/log/test.log ADDED
File without changes
data/public/404.html ADDED
@@ -0,0 +1,8 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+ "http://www.w3.org/TR/html4/loose.dtd">
3
+ <html>
4
+ <body>
5
+ <h1>File not found</h1>
6
+ <p>Change this error message for pages not found in public/404.html</p>
7
+ </body>
8
+ </html>
data/public/500.html ADDED
@@ -0,0 +1,8 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+ "http://www.w3.org/TR/html4/loose.dtd">
3
+ <html>
4
+ <body>
5
+ <h1>Application error (Apache)</h1>
6
+ <p>Change this error message for exceptions thrown outside of an action (like in Dispatcher setups or broken Ruby code) in public/500.html</p>
7
+ </body>
8
+ </html>
Binary file
@@ -0,0 +1,7 @@
1
+ body {
2
+ margin: 0 auto; width: 80%;
3
+ background-image: url('/bacu-bat.png');
4
+ background-repeat: no-repeat; background-position: 8px 8px;
5
+ }
6
+ pre { font-weight: bold; use-normal-font-size: larger; }
7
+ hr { width: 30%; }
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
4
+
5
+ # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
6
+ # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
7
+ require "dispatcher"
8
+
9
+ ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
10
+ Dispatcher.dispatch
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # You may specify the path to the FastCGI crash log (a log of unhandled
4
+ # exceptions which forced the FastCGI instance to exit, great for debugging)
5
+ # and the number of requests to process before running garbage collection.
6
+ #
7
+ # By default, the FastCGI crash log is RAILS_ROOT/log/fastcgi.crash.log
8
+ # and the GC period is nil (turned off). A reasonable number of requests
9
+ # could range from 10-100 depending on the memory footprint of your app.
10
+ #
11
+ # Example:
12
+ # # Default log path, normal GC behavior.
13
+ # RailsFCGIHandler.process!
14
+ #
15
+ # # Default log path, 50 requests between GC.
16
+ # RailsFCGIHandler.process! nil, 50
17
+ #
18
+ # # Custom log path, normal GC behavior.
19
+ # RailsFCGIHandler.process! '/var/log/myapp_fcgi_crash.log'
20
+ #
21
+ require File.dirname(__FILE__) + "/../config/environment"
22
+ require 'fcgi_handler'
23
+
24
+ RailsFCGIHandler.process!
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
4
+
5
+ # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
6
+ # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
7
+ require "dispatcher"
8
+
9
+ ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
10
+ Dispatcher.dispatch
Binary file
data/public/home.html ADDED
@@ -0,0 +1,108 @@
1
+ <html>
2
+ <head>
3
+ <title>Bacuview -- a Bacula Status Monitor</title>
4
+ <link href="/bacuweb.css" rel="Stylesheet"
5
+ media="screen" type="text/css" />
6
+ </head>
7
+ <body>
8
+ <div style="text-align: center"> <hr width="30%"/>
9
+ <h1>Bacuview -- a Bacula Status Monitor</h1>
10
+ </div>
11
+
12
+ <p> The Bacuview application provides a web-based view into the
13
+ status of a Bacula backup system. Views are provided for the status
14
+ of the jobs, the clients, the media, and the pools of the
15
+ system. </p>
16
+
17
+ <p> Bacuview was developed in surprisingly short order thanks
18
+ largely to the use of the <a href="http://rubyonrails.org/"> Ruby on Rails
19
+ </a> development framework and the <a href="http://ruby-doc.org/">
20
+ Ruby </a> programming language. The Bacuview application is
21
+ generously hosted at <a href="http://rubyforge.org/"> RubyForge</a>,
22
+ where the project is available <a
23
+ href="http://rubyforge.org/frs/?group_id=1288"> for download. </a>
24
+ </p>
25
+
26
+ <p> If this sounds like something that you might find useful, you
27
+ can take a look at the <a href="news.html">news</a> and <a
28
+ href="ChangeLog">ChangeLog</a> files, and review the <a
29
+ href="install.html"> installation notes </a> prior to getting
30
+ started. </p>
31
+
32
+ <div style="text-align: center"> <hr width="30%"/>
33
+ <h2>The Job View</h2>
34
+
35
+ <a href="jobs.png"> <img src="jobs-thumb.png"/> </a>
36
+ <a href="job-1449.png"> <img src="job-1449-thumb.png"/> </a>
37
+ <a href="job-last.png"> <img src="job-last-thumb.png"/> </a>
38
+ </div>
39
+
40
+ <p> The most useful view into the status of a Bacula system is
41
+ provided by the Jobs view, which will initially show the completion
42
+ status of all jobs that have been scheduled during the current
43
+ day. </p>
44
+
45
+ <p> The "Jobs..." links along the left of the page are sticky, so
46
+ you can get a list of all "bubba" jobs run in the last month by
47
+ selecting the appropriate "Job..." links in any order. </p>
48
+
49
+ <p> The contents of the jobs table can be sorted by clicking the
50
+ links in the column headings of the table. Sorting on the same
51
+ column multiple times will toggle the sort order. The current sort
52
+ column is indicated by a black bar under the column header.
53
+
54
+ <p> Clicking the "Job Id" link for a job will provide a more
55
+ detailed view of the information available for that job. One of the
56
+ more useful features of this page is that it provides an easy way to
57
+ find out the media volumes that are used by a job. Clicking the
58
+ "Job Name" link will provide a summary of the last backups of the
59
+ job. </p>
60
+
61
+ <div style="text-align: center"> <hr width="30%">
62
+ <h2>The Media View</h2>
63
+
64
+ <a href="media.png"> <img src="media-thumb.png"/> </a>
65
+ <a href="media-39.png"> <img src="media-39-thumb.png"/> </a>
66
+ </div>
67
+
68
+ <p> The Media view shows the current status of all the media volumes
69
+ registered with Bacula, as well as some information about the pool
70
+ to which each volume belongs. As with the Jobs view, the Media
71
+ table can be sorted by clicking the links in the column headers,
72
+ with a more detailed report on each volume available by following
73
+ the link that shows the label of the volume. </p>
74
+
75
+ <div style="text-align: center"> <hr width="30%">
76
+ <h2>The Client View</h2>
77
+
78
+ <a href="clients.png"> <img src="clients-thumb.png"/> </a>
79
+ <a href="client-sophie.png"> <img src="client-sophie-thumb.png"/> </a>
80
+ </div>
81
+
82
+ <p> The Client view shows what information is available on each of
83
+ the clients that are registered with Bacula. If you've enabled
84
+ Javascript support in your web browser, you can also perform a quick
85
+ status check on any of all of the clients by clicking the "OK?"
86
+ column. The page detailing the information on a particular client
87
+ is provided for consistancy, even though it supplies no additional
88
+ information. </p>
89
+
90
+ <div style="text-align: center"> <hr width="30%">
91
+ <h2>The Pool View</h2>
92
+
93
+ <a href="pools.png"> <img src="pools-thumb.png"/> </a>
94
+ <a href="pool-lto3.png"> <img src="pool-lto3-thumb.png"/> </a>
95
+ </div>
96
+
97
+ <p> The Pool view summarized the pools available for backups. Its
98
+ primary value is as a way to select one of the detailed views of a
99
+ particular pool, where a great deal of information is
100
+ available. </p>
101
+
102
+ <div style="text-align: center"> <hr width="30%">
103
+ <address>
104
+ <a href="mailto:john@kodis.org">John Kodis</a>
105
+ </address>
106
+ </div>
107
+ </body>
108
+ </html>
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,156 @@
1
+ <html>
2
+ <head>
3
+ <title>Bacuview Installation</title>
4
+ <link href="/bacuweb.css" rel="Stylesheet"
5
+ media="screen" type="text/css" />
6
+ </head>
7
+ <body>
8
+ <div class='head'>
9
+ <hr/><h1>Bacuview Installation</h1>
10
+ </div>
11
+
12
+ <div class='head'> <hr/>
13
+ <h2>OVERVIEW</h2>
14
+ </div>
15
+
16
+ <p> The Bacuview application has been developed using the Ruby on
17
+ Rails framework, as described at <a
18
+ href='http://rubyonrails.org'>the Ruby on Rails</a> web site. While
19
+ this greatly speeds development, it adds a few prerequisites to the
20
+ application. The installation procedure involves installing Ruby,
21
+ using Ruby to build RubyGems, the Ruby package manager, and finally
22
+ using the resulting gem command to install the Ruby on Rails package
23
+ and the Bacuview application. After a few configuration file changes
24
+ your Bacuview installation should be operational. </p>
25
+
26
+ <div class='head'> <hr/>
27
+ <h2>INSTALL RUBY</h2>
28
+ </div>
29
+
30
+ <p> It's best to install as much of the required software using the
31
+ packaging system provided by your operating system. For Fedora Core
32
+ 6 and derived operating systems, this should cover all the bases:
33
+ </p>
34
+
35
+ <pre>
36
+ $ su -
37
+ # yum install ruby ruby-rdoc ruby-postgres ruby-mysql </pre>
38
+
39
+ <p> Of course, you could also simply "yum install \*ruby\*" to get
40
+ all the Ruby goodness that Fedora has to offer, while at the other
41
+ extreme you could omit either ruby-postgress or ruby-mysql. </p>
42
+
43
+ <div class='head'> <hr/>
44
+ <h2>INSTALL RUBYGEMS</h2>
45
+ </div>
46
+
47
+ <p> RubyGems, the Ruby package manager is installed next. The
48
+ RubyGems application is distributed as a tar file containing a
49
+ "setup.rb" Ruby script that handles the RubyGems installation and
50
+ setup. As with Ruby itself, rubygems is available for <a
51
+ href="http://rubyforge.org/frs/download.php/11289/rubygems-0.9.0.tgz">
52
+ download </a> from the rubyforge.org web site. </p>
53
+
54
+ <p> Given the rubygems-0.9.0.tgz file... </p>
55
+
56
+ <pre>
57
+ $ tar xzf rubygems-0.9.0.tgz
58
+ $ su -
59
+ # cd rubygems-0.9.0
60
+ # ruby setup.rb </pre>
61
+
62
+ <div class='head'> <hr/>
63
+ <h2>INSTALL RAILS AND BACUVIEW</h2>
64
+ </div>
65
+
66
+ <p> With the RubyGems package available, the installation of the
67
+ Bacuview web application and the Ruby on Rails framework that it
68
+ uses is trivial: </p>
69
+
70
+ <pre>
71
+ # gem install rails --include-dependencies
72
+ # gem install bacuview </pre>
73
+
74
+ <div class='head'> <hr/>
75
+ <h2>CREATE A BACUVIEW USER</h2>
76
+ </div>
77
+
78
+ <p> While strictly optional, you can protect your bacula database
79
+ against inadvertent modification by the Bacuview application by
80
+ setting up a "bacuview" database user that has select-only rights to
81
+ the few tables that the Bacuview application uses. As the postgres
82
+ user, or whatever user has administrative rights to your database:
83
+ </p>
84
+
85
+ <pre>
86
+ $ psql bacula
87
+ # create user bacuview password 'bacuview';
88
+ # grant select on job, jobmedia, client, media, pool to bacuview; </pre>
89
+
90
+ <p> It may also be necessary to add lines to the pg_hba.conf file to
91
+ allow the bacuview user to connect to the bacula database: </p>
92
+
93
+ <pre>
94
+ local bacula bacuview md5
95
+ host bacula bacuview 127.0.0.1/32 md5 </pre>
96
+
97
+ <div class='head'> <hr/>
98
+ <h2>CONFIGURE BACUVIEW</h2>
99
+ </div>
100
+
101
+ <p> Local configurations are performed through two configuration
102
+ files, config/database.yml and bacuview/custom.yml. Begin by copying
103
+ over the supplied template files: </p>
104
+
105
+ <pre>
106
+ # cd /usr/lib/ruby/gems/1.8/gems/bacuview/config
107
+ # cp database.yml.template database.yml
108
+ # cp bacuview.yml.template bacuview.yml </pre>
109
+
110
+ <p> The database.yml file is initially set up for a Postgres
111
+ database running on the local machine, accessing a database instance
112
+ named bacula and accessed by the bacuview user with a password of
113
+ bacuview. For a MySQL database, use 'adapter: mysql', and edit the
114
+ other parameters appropriately. </p>
115
+
116
+ <p> The bacuview.yml file is currently used only to allow Bacuview
117
+ to find the Bacula configuration files so that the mapping between
118
+ client names and host names can be extracted for use by the client
119
+ status check. If these are kept in /etc/bacula, no changes should
120
+ be required. </p>
121
+
122
+ <div class='head'> <hr/>
123
+ <h2>STARTUP</h2>
124
+ </div>
125
+
126
+ <p> The simplest way to run the Baculview application is to use
127
+ WEBrick, the web server supplied with the Rails framework. In the
128
+ gem installation, /usr/bin/bacuview is a simple wrapper script that
129
+ runs the WEBrick server: </p>
130
+
131
+ <pre>
132
+ $ /usr/sbin/bacuview
133
+ => Booting WEBrick...
134
+ => Rails application started on http://0.0.0.0:3000 </pre>
135
+
136
+ <p> If all is well, you should be able to access the initial
137
+ Bacuview web page by pointing your web browser to the URL shown in
138
+ the server startup message, http://0.0.0.0:3000 </p>
139
+
140
+ <p> If so, congratulations, and welcome to Bacuview! </p>
141
+
142
+ <p> Once you're satisfied that all is well, you may want to switch
143
+ to the Bacuview production environment, which is slightly faster and
144
+ which gives less informative error messages. You may also want to
145
+ run the server as a daemon, and to use a more standard web server
146
+ port. This can be done by passing options when starting the web
147
+ server: </p>
148
+
149
+ <pre>
150
+ $ bacuview -d -e production -p 8080 </pre>
151
+
152
+ <div class='head'> <hr/>
153
+ <address> <a href="mailto:john@kodis.org">John Kodis</a> </address>
154
+ </div>
155
+ </body>
156
+ </html>
@@ -0,0 +1,2 @@
1
+ // Place your application-specific JavaScript functions and classes here
2
+ // This file is automatically included by javascript_include_tag :defaults
@@ -0,0 +1,24 @@
1
+ function check(n) {
2
+ document.getElementById("client-" + n).innerHTML =
3
+ '<img src="/images/busy.png" class="em1"/>';
4
+ var req = new XMLHttpRequest();
5
+ req.open("GET", "/client/check?id=" + n);
6
+ req.onreadystatechange = function() {
7
+ if (req.readyState == 4) {
8
+ document.getElementById("client-" + n).innerHTML = req.responseText;
9
+ }
10
+ }
11
+ req.send(null);
12
+ return false;
13
+ }
14
+
15
+ function check_through(n) {
16
+ for (i=1; i<=n; i++) {
17
+ check(i);
18
+ }
19
+ return false;
20
+ }
21
+
22
+ function js_hide() {
23
+ document.getElementById("js").innerHTML = "";
24
+ }