update for desktop widgets
|
@ -0,0 +1,61 @@
|
|||
class DesktopWidgetsController < OrbitBackendController
|
||||
require "net/http"
|
||||
require "uri"
|
||||
require 'zip/zip'
|
||||
|
||||
def index
|
||||
end
|
||||
|
||||
def upload
|
||||
if !params[:desktop_widget].nil?
|
||||
temp_file = Tempfile.new("temp_file")
|
||||
original_file = params[:desktop_widget][:package_file]
|
||||
#if original_file.content_type == 'application/zip'
|
||||
temp_file.write(original_file.read.force_encoding('UTF-8'))
|
||||
temp_file.rewind
|
||||
filename = File.basename(original_file.original_filename,".zip")
|
||||
unzip_widget(temp_file, filename)
|
||||
#else
|
||||
# flash[:error] = "Upload file should be in zip format"
|
||||
#end
|
||||
temp_file.close
|
||||
end
|
||||
end
|
||||
|
||||
def unzip_widget(file, zip_name)
|
||||
Zip::ZipFile.open(file) { |zip_file|
|
||||
dw = DesktopWidget.new.from_json(zip_file.read("#{zip_name}/settings.json"))
|
||||
Dir.mktmpdir('f_path') { |dir|
|
||||
javascripts_entries = []
|
||||
images_entries = []
|
||||
|
||||
zip_file.entries.each do |entry|
|
||||
case (path = entry.to_s)
|
||||
when /\A(#{zip_name})\/(default\.css)\z/ #for default css
|
||||
dw.build_css_default(:file => get_temp_file(zip_file, dir, entry))
|
||||
when /\A(#{zip_name})\/(widget\.html)\z/ #for layout html
|
||||
dw.build_widget_layout(:file => get_temp_file(zip_file, dir, entry))
|
||||
when /\A(#{zip_name})\/(javascripts)\/.*(\.js)\z/ #for js
|
||||
javascripts_entries << entry
|
||||
when /\A(#{zip_name})\/(images)\/.*((\.jpg)|(\.png)|(\.gif))\z/ #for img
|
||||
images_entries << entry
|
||||
end
|
||||
end
|
||||
|
||||
['javascripts', 'images'].each do |type|
|
||||
eval("#{type}_entries").each do |entry|
|
||||
eval("dw.#{type}").build(:file => get_temp_file(zip_file, dir, entry))
|
||||
end
|
||||
end
|
||||
}
|
||||
dw.save
|
||||
}
|
||||
end
|
||||
def get_temp_file(zip_file, dir, entry)
|
||||
filename = File.basename(entry.to_s)
|
||||
temp_file = File.new(dir + '/' + filename, 'w+')
|
||||
temp_file.write (zip_file.read entry ).force_encoding('UTF-8')
|
||||
temp_file
|
||||
end
|
||||
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
class OtheraccountsController< ApplicationController
|
||||
class Desktop::OtheraccountsController< ApplicationController
|
||||
require 'open-uri'
|
||||
require 'rexml/document'
|
||||
require 'net/http'
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class CssDefault < Stylesheet
|
||||
|
||||
belongs_to :design
|
||||
belongs_to :desktop_widget
|
||||
|
||||
end
|
||||
|
|
|
@ -11,6 +11,7 @@ class Image
|
|||
mount_uploader :file, ImageUploader
|
||||
|
||||
belongs_to :design
|
||||
belongs_to :desktop_widget
|
||||
|
||||
before_save :set_name
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
class Javascript < DesignFile
|
||||
belongs_to :design
|
||||
belongs_to :desktop_widget
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class Stylesheet < DesignFile
|
||||
belongs_to :design
|
||||
belongs_to :desktop_widget
|
||||
mount_uploader :file_orig, AssetUploader
|
||||
|
||||
def parse_urls
|
||||
|
@ -32,5 +33,35 @@ class Stylesheet < DesignFile
|
|||
self.save
|
||||
}
|
||||
end
|
||||
def parse_widgets_urls
|
||||
orig_content = content = self.file.read.force_encoding("UTF-8")
|
||||
# self.remove_file!
|
||||
# self.remove_file_orig!
|
||||
names = []
|
||||
images = self.desktop_widget.images
|
||||
content.scan(/(?<=url)(.*?)(?=\))/){
|
||||
css_name = $1.gsub(' ','').gsub('(','')
|
||||
name = File.basename(css_name).gsub(/[\\\"]/, '')
|
||||
image = images.detect{ |i| i.file_identifier.eql?(name) } rescue nil
|
||||
image.update_attribute(:in_css, true) if image
|
||||
file_name = image.file_url rescue nil
|
||||
names << [css_name, file_name]
|
||||
}
|
||||
names.each do |name|
|
||||
content.gsub!(name[0], name[1]) if name[1]
|
||||
end
|
||||
Dir.mktmpdir('f_path') { |dir|
|
||||
orig_file_name = self.file_identifier
|
||||
|
||||
temp_file = File.new(dir + '/' + orig_file_name, 'w+')
|
||||
temp_file.write orig_content.force_encoding("UTF-8")
|
||||
self.file_orig = temp_file
|
||||
|
||||
temp_file = File.new(dir + '/' + orig_file_name, 'w+')
|
||||
temp_file.write content.force_encoding("UTF-8")
|
||||
self.file = temp_file
|
||||
self.save
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ class Desktop
|
|||
belongs_to :user
|
||||
|
||||
has_many :sections, :autosave => true, :dependent => :destroy
|
||||
has_many :desktop_widgets, :autosave => true, :dependent => :destroy
|
||||
# has_many :desktop_widgets, :autosave => true, :dependent => :destroy
|
||||
|
||||
before_create :initialize_section
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
class DesktopWidget
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
include ParserLayoutWidget
|
||||
|
||||
field :name
|
||||
field :author
|
||||
field :shape
|
||||
field :version, :type => String
|
||||
|
||||
has_one :css_default, :autosave => true, :dependent => :destroy
|
||||
has_one :widget_layout, :autosave => true, :dependent => :destroy
|
||||
has_many :images, :autosave => true, :dependent => :destroy
|
||||
has_many :javascripts, :autosave => true, :dependent => :destroy
|
||||
|
||||
accepts_nested_attributes_for :images, :allow_destroy => true
|
||||
accepts_nested_attributes_for :javascripts, :allow_destroy => true
|
||||
|
||||
after_save :parse_css_for_images
|
||||
|
||||
# belongs_to :desktop
|
||||
|
||||
|
||||
protected
|
||||
|
||||
def parse_css_for_images
|
||||
self.css_default.parse_widgets_urls
|
||||
parse_widget_for_images(self)
|
||||
end
|
||||
|
||||
end
|
|
@ -9,6 +9,5 @@ class Tile
|
|||
field :title
|
||||
|
||||
belongs_to :group
|
||||
|
||||
|
||||
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
class WidgetLayout < DesignFile
|
||||
|
||||
attr_reader :content
|
||||
|
||||
field :body
|
||||
|
||||
belongs_to :desktop_widget
|
||||
|
||||
|
||||
def content
|
||||
self.file.read.force_encoding("UTF-8") rescue ''
|
||||
end
|
||||
|
||||
def self.exist_one?
|
||||
WidgetLayout.count > 0
|
||||
end
|
||||
|
||||
end
|
|
@ -1,13 +0,0 @@
|
|||
class DesktopWidget
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
|
||||
field :name
|
||||
field :author
|
||||
field :shape
|
||||
field :desktop_id
|
||||
field :status
|
||||
field :section
|
||||
|
||||
belongs_to :desktop
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
<h4>Upload Widget Package </h4>
|
||||
<div class="main2">
|
||||
<%= form_tag '',:multipart => true,:action=>"post" do |f| %>
|
||||
|
||||
<p>
|
||||
<%= file_field :desktop_widget,:package_file %>
|
||||
</p>
|
||||
<%= submit_tag %>
|
||||
|
||||
<% end %>
|
||||
|
||||
</div>
|
|
@ -33,6 +33,7 @@ module Orbit
|
|||
config.autoload_paths += %W(#{config.root}/app/models/meta)
|
||||
config.autoload_paths += %W(#{config.root}/app/models/purchase)
|
||||
config.autoload_paths += %W(#{config.root}/app/models/user)
|
||||
config.autoload_paths += %W(#{config.root}/app/models/desktop)
|
||||
|
||||
# Include all helpers
|
||||
# 'helper :all' must be removed in ApplicationController
|
||||
|
|
|
@ -143,7 +143,17 @@ Orbit::Application.routes.draw do
|
|||
resources :users
|
||||
end
|
||||
|
||||
match '/desktop/'=>'desktop#index'
|
||||
resources :desktop_widgets do
|
||||
collection do
|
||||
get 'upload'
|
||||
get 'delete'
|
||||
post 'upload'
|
||||
end
|
||||
end
|
||||
|
||||
namespace :desktop do
|
||||
|
||||
match "/"=>"desktop#index"
|
||||
|
||||
# Sinatra Routes start
|
||||
|
||||
|
@ -178,46 +188,46 @@ Orbit::Application.routes.draw do
|
|||
|
||||
# Sinatra Routes end
|
||||
|
||||
match '/desktop/desktop'=>'desktop#desktop'
|
||||
match '/desktop/app_manager'=>'desktop#app_manager'
|
||||
match '/desktop/sections'=>'desktop#sections'
|
||||
match '/desktop/settings'=>'desktop#settings'
|
||||
match '/desktop/get_desktop_settings/'=>'desktop#get_desktop_settings'
|
||||
match '/desktop/save_desktop_settings/'=>'desktop#save_desktop_settings'
|
||||
match '/desktop/getgroups/'=>'desktop#getgroups'
|
||||
match '/desktop/getsectionlist/'=>'desktop#getsectionlist'
|
||||
match '/desktop/settingthemes/'=>'desktop#settingthemes'
|
||||
match '/desktop/settingsections/'=>'desktop#settingsections'
|
||||
match '/desktop/getapplist/'=>'desktop#getapplist'
|
||||
match '/desktop/newpositions/'=>'desktop#newpositions'
|
||||
match '/desktop/settingconnection/'=>'desktop#settingconnection'
|
||||
match '/desktop'=>'desktop#desktop'
|
||||
match '/app_manager'=>'desktop#app_manager'
|
||||
match '/sections'=>'desktop#sections'
|
||||
match '/settings'=>'desktop#settings'
|
||||
match '/get_desktop_settings/'=>'desktop#get_desktop_settings'
|
||||
match '/save_desktop_settings/'=>'desktop#save_desktop_settings'
|
||||
match '/getgroups/'=>'desktop#getgroups'
|
||||
match '/getsectionlist/'=>'desktop#getsectionlist'
|
||||
match '/settingthemes/'=>'desktop#settingthemes'
|
||||
match '/settingsections/'=>'desktop#settingsections'
|
||||
match '/getapplist/'=>'desktop#getapplist'
|
||||
match '/newpositions/'=>'desktop#newpositions'
|
||||
match '/settingconnection/'=>'desktop#settingconnection'
|
||||
|
||||
|
||||
match '/desktop/journal_p/'=>'desktop_publications#journal_p'
|
||||
match '/desktop/journal_p_list/'=>'desktop_publications#journal_p_list'
|
||||
match '/desktop/journal_p_add/'=>'desktop_publications#journal_p_add'
|
||||
match '/desktop_publications/getjournals' => 'desktop_publications#getjournals'
|
||||
match '/desktop/books' => 'desktop_publications#books'
|
||||
match '/desktop/books_list/'=>'desktop_publications#books_list'
|
||||
match '/desktop/books_add/'=>'desktop_publications#books_add'
|
||||
match '/journal_p/'=>'desktop_publications#journal_p'
|
||||
match '/journal_p_list/'=>'desktop_publications#journal_p_list'
|
||||
match '/journal_p_add/'=>'desktop_publications#journal_p_add'
|
||||
match '/books' => 'desktop_publications#books'
|
||||
match '/books_list/'=>'desktop_publications#books_list'
|
||||
match '/books_add/'=>'desktop_publications#books_add'
|
||||
|
||||
match '/desktop/seminar_p' => 'desktop_publications#seminar_p'
|
||||
match '/desktop/seminar_p_list/'=>'desktop_publications#seminar_p_list'
|
||||
match '/desktop/seminar_p_add/'=>'desktop_publications#seminar_p_add'
|
||||
match '/seminar_p' => 'desktop_publications#seminar_p'
|
||||
match '/seminar_p_list/'=>'desktop_publications#seminar_p_list'
|
||||
match '/seminar_p_add/'=>'desktop_publications#seminar_p_add'
|
||||
|
||||
match '/desktop/research_d' => 'desktop_research#research_d'
|
||||
match '/desktop/research_d_list/' => 'desktop_research#research_d_list'
|
||||
match '/desktop/research_d_add' => 'desktop_research#research_d_add'
|
||||
match '/research_d' => 'desktop_research#research_d'
|
||||
match '/research_d_list/' => 'desktop_research#research_d_list'
|
||||
match '/research_d_add' => 'desktop_research#research_d_add'
|
||||
|
||||
match '/desktop/research_p' => 'desktop_research#research_p'
|
||||
match '/desktop/research_p_list/' => 'desktop_research#research_p_list'
|
||||
match '/desktop/research_p_add' => 'desktop_research#research_p_add'
|
||||
match '/research_p' => 'desktop_research#research_p'
|
||||
match '/research_p_list/' => 'desktop_research#research_p_list'
|
||||
match '/research_p_add' => 'desktop_research#research_p_add'
|
||||
match '/temp_func/'=>'desktop#temp_func'
|
||||
end
|
||||
|
||||
|
||||
match '/desktop/twitter/'=>'otheraccounts#twitter'
|
||||
match '/desktop/forgmail/'=>'otheraccounts#gmail'
|
||||
match '/desktop/getaccounts'=>'otheraccounts#getaccounts'
|
||||
match '/desktop/save_account_info/'=>'otheraccounts#saveaccountinfo'
|
||||
match '/twitter/'=>'otheraccounts#twitter'
|
||||
match '/forgmail/'=>'otheraccounts#gmail'
|
||||
match '/getaccounts'=>'otheraccounts#getaccounts'
|
||||
match '/save_account_info/'=>'otheraccounts#saveaccountinfo'
|
||||
|
||||
match '/desktop_appstore/appstore'=>'desktop_appstore#appstore'
|
||||
match '/desktop_appstore/widgets'=>'desktop_appstore#widgets'
|
||||
|
@ -228,13 +238,14 @@ Orbit::Application.routes.draw do
|
|||
|
||||
match '/desktop_orbit/eventajaxload'=> 'desktop_orbit#eventajaxload'
|
||||
match '/desktop_orbit/gettimelinespan' => 'desktop_orbit#gettimelinespan'
|
||||
match '/desktop_publications/getjournals' => 'desktop_publications#getjournals'
|
||||
|
||||
#match '/desktop_orbit/eventajaxload' => 'desktop_publications#create_journal'
|
||||
#match '/desktop_orbit/eventajaxload' => 'desktop_publications#delete_journal'
|
||||
# match '/desktop_orbit/eventajaxload' => 'desktop_publications#update_journal'
|
||||
|
||||
|
||||
match '/desktop/temp_func/'=>'desktop#temp_func'
|
||||
|
||||
|
||||
match '/panel/:app_name/front_end/:app_action/:id(/:controller_action)' => 'pages#show_from_link', :constraints => lambda { |request|
|
||||
!request.query_string.include?("inner=true")
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
module ParserLayoutWidget
|
||||
require 'nokogiri'
|
||||
|
||||
def parse_widget_for_images(widget)
|
||||
widge = Nokogiri::HTML(widget.widget_layout.body)
|
||||
|
||||
widge.css('.widget_image').each do |page_image|
|
||||
image = widget.images.where( file: File.basename(page_image['src']))[0]
|
||||
image.update_attributes(:html_id => page_image['id'], :html_class => page_image['class'], :in_html => true) if image
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -1,81 +0,0 @@
|
|||
<link href="http://fonts.googleapis.com/css?family=Rationale|Orbitron" rel="stylesheet" type="text/css">
|
||||
<style>
|
||||
.clock{
|
||||
/* The .clock div. Created dynamically by jQuery */
|
||||
background-color:#111;
|
||||
height:75px;
|
||||
width:75px;
|
||||
position:relative;
|
||||
overflow:hidden;
|
||||
float:left;
|
||||
}
|
||||
|
||||
.clock .rotate{
|
||||
/* There are two .rotate divs - one for each half of the background */
|
||||
position:absolute;
|
||||
width:75px;
|
||||
height:75px;
|
||||
top:0;
|
||||
left:0;
|
||||
}
|
||||
|
||||
.rotate.right{
|
||||
display:none;
|
||||
z-index:9;
|
||||
}
|
||||
|
||||
.clock .bg, .clock .front{
|
||||
width:37.5px;
|
||||
height:75px;
|
||||
background-color:#111;
|
||||
position:absolute;
|
||||
top:0;
|
||||
}
|
||||
|
||||
.clock .display{
|
||||
/* Holds the number of seconds, minutes or hours respectfully */
|
||||
position:absolute;
|
||||
width:75px;
|
||||
font-family: Orbitron, sans-serif;
|
||||
z-index:17;
|
||||
color:#F5F5F5;
|
||||
font-size:21px;
|
||||
text-align:center;
|
||||
top:27.5px;
|
||||
left:0px;
|
||||
|
||||
}
|
||||
|
||||
/* The left part of the background: */
|
||||
|
||||
.clock .bg.left{ left:0px; }
|
||||
|
||||
/* Individual styles for each color: */
|
||||
.orange .bg.left{ background:url(desktop_widgets/4fa7810ac88514014d7c59bc/img/bg_orange.png) no-repeat left top; }
|
||||
.green .bg.left{ background:url(desktop_widgets/4fa7810ac88514014d7c59bc/img/bg_green.png) no-repeat left top; }
|
||||
.blue .bg.left{ background:url(desktop_widgets/4fa7810ac88514014d7c59bc/img/bg_blue.png) no-repeat left top; }
|
||||
|
||||
/* The right part of the background: */
|
||||
.clock .bg.right{ left:37.5px; }
|
||||
|
||||
.orange .bg.right{ background:url(desktop_widgets/4fa7810ac88514014d7c59bc/img/bg_orange.png) no-repeat right top; }
|
||||
.green .bg.right{ background:url(desktop_widgets/4fa7810ac88514014d7c59bc/img/bg_green.png) no-repeat right top; }
|
||||
.blue .bg.right{ background:url(desktop_widgets/4fa7810ac88514014d7c59bc/img/bg_blue.png) no-repeat right top; }
|
||||
|
||||
|
||||
.clock .front.left{
|
||||
left:0;
|
||||
z-index:15;
|
||||
}
|
||||
#fancyClock {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -36px 0 0 -114px;
|
||||
}
|
||||
</style>
|
||||
<div id="fancyClock"></div>
|
||||
<script>
|
||||
$('#fancyClock').tzineClock();
|
||||
</script>
|
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 16 KiB |
|
@ -1,45 +0,0 @@
|
|||
<style type="text/css">
|
||||
.g_weather { position: relative; height: 198px; }
|
||||
.g_weather img { float: left; display: block; margin: 0; padding: 12px; }
|
||||
.g_weather .gw_recent {
|
||||
overflow: hidden;
|
||||
height: 96%;
|
||||
padding-top: 4%;
|
||||
}
|
||||
.g_weather .gw_weekly { display: none; }
|
||||
.g_weather .gw_location {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.g_weather .gw_condition_des { font-size: 22px; }
|
||||
.g_weather .gw_temp { margin-top: 26px; }
|
||||
.g_weather .gw_temp_num { font-size: 56px; }
|
||||
.g_weather .gw_temp_unit { font-size: 26px; }
|
||||
.g_weather .gw_forecast {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
</style>
|
||||
<div class="g_weather">
|
||||
<div class="gw_recent">
|
||||
<img src="desktop_widgets/4fa7817cc88514014d7c59c2/img/sunny.png" alt="sunny" class="gw_condition">
|
||||
<div class="gw_temp">
|
||||
<span class="gw_temp_num thmtxt">29</span><span class="gw_temp_unit thmtxt">°C</span>
|
||||
</div>
|
||||
<div class="gw_condition_des thmtxt">Sunny</div>
|
||||
</div>
|
||||
<div class="gw_weekly">
|
||||
weekly report
|
||||
</div>
|
||||
<div class="gw_location thmtxt">Hsin-Chu</div>
|
||||
<a href="" class="gw_forecast thmtxt">> Weekly Report</a>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
g_weather();
|
||||
</script>
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"author" : "Harry",
|
||||
"name" : "Clock",
|
||||
"shape" : "w2 h1",
|
||||
"version" : "1.0"
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<link href="http://fonts.googleapis.com/css?family=Rationale|Orbitron" rel="stylesheet" type="text/css">
|
||||
<div id="fancyClock"></div>
|
||||
<script>
|
||||
$('#fancyClock').tzineClock();
|
||||
</script>
|
|
@ -0,0 +1,26 @@
|
|||
.g_weather { position: relative; height: 198px; }
|
||||
.g_weather img { float: left; display: block; margin: 0; padding: 12px; }
|
||||
.g_weather .gw_recent {
|
||||
overflow: hidden;
|
||||
height: 96%;
|
||||
padding-top: 4%;
|
||||
}
|
||||
.g_weather .gw_weekly { display: none; }
|
||||
.g_weather .gw_location {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.g_weather .gw_condition_des { font-size: 22px; }
|
||||
.g_weather .gw_temp { margin-top: 26px; }
|
||||
.g_weather .gw_temp_num { font-size: 56px; }
|
||||
.g_weather .gw_temp_unit { font-size: 26px; }
|
||||
.g_weather .gw_forecast {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"author" : "Devin",
|
||||
"name" : "Weather",
|
||||
"shape" : "w2 h2",
|
||||
"version" : "0.0"
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<div class="g_weather">
|
||||
<div class="gw_recent">
|
||||
<img src="desktop_widgets/4fa7817cc88514014d7c59c2/img/sunny.png" alt="sunny" class="gw_condition widget_image">
|
||||
<div class="gw_temp">
|
||||
<span class="gw_temp_num thmtxt">29</span><span class="gw_temp_unit thmtxt">°C</span>
|
||||
</div>
|
||||
<div class="gw_condition_des thmtxt">Sunny</div>
|
||||
</div>
|
||||
<div class="gw_weekly">
|
||||
weekly report
|
||||
</div>
|
||||
<div class="gw_location thmtxt">Hsin-Chu</div>
|
||||
<a href="" class="gw_forecast thmtxt">> Weekly Report</a>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
g_weather();
|
||||
</script>
|