Loading...
62 |
63 |
64 | ' ).html( g_cmn.cmn_param['nowbrowsing_text'] ).text() + item.attr( 'pagetitle' ) + ' - ' + item.attr( 'url' );
40 |
41 | var pid = IsUnique( 'tweetbox' );
42 | var left = null;
43 | var top = null;
44 | var width = 324;
45 |
46 | var SetText = function() {
47 | var areatext = $( '#tweetbox_text' ).val();
48 | var pos = $( '#tweetbox_text' ).get( 0 ).selectionStart;
49 | var bef = areatext.substr( 0, pos );
50 | var aft = areatext.substr( pos, areatext.length );
51 |
52 | $( '#tweetbox_text' ).val( bef + text + aft )
53 | .focus()
54 | .trigger( 'keyup' );
55 | };
56 |
57 | // ツイートパネルが開いていない場合は開く
58 | if ( pid == null )
59 | {
60 | var _cp = new CPanel( left, top, width, 240 );
61 | _cp.SetType( 'tweetbox' );
62 | _cp.SetParam( { account_id: '', rep_user: null, hashtag: null } );
63 | _cp.Start( function() {
64 | if ( $( '#tweetbox_text' ).length ) {
65 | SetText();
66 | $( '#tweetbox_text' ).SetPos( 'start' );
67 | }
68 | } );
69 | }
70 | else
71 | {
72 | SetText();
73 | }
74 |
75 | e.stopPropagation();
76 | } );
77 |
78 | cont.trigger( 'contents_resize' );
79 | } );
80 | };
81 |
82 | ////////////////////////////////////////////////////////////
83 | // 開始処理
84 | ////////////////////////////////////////////////////////////
85 | this.start = function() {
86 | ////////////////////////////////////////
87 | // 最小化/設定切替時のスクロール位置
88 | // 保存/復元
89 | ////////////////////////////////////////
90 | cont.on( 'contents_scrollsave', function( e, type ) {
91 | // 保存
92 | if ( type == 0 )
93 | {
94 | if ( scrollPos == null )
95 | {
96 | scrollPos = nowbrowsing_list.scrollTop();
97 | }
98 | }
99 | // 復元
100 | else
101 | {
102 | if ( scrollPos != null )
103 | {
104 | nowbrowsing_list.scrollTop( scrollPos );
105 | scrollPos = null;
106 | }
107 | }
108 | } );
109 |
110 | ////////////////////////////////////////
111 | // リサイズ処理
112 | ////////////////////////////////////////
113 | cont.on( 'contents_resize', function() {
114 | $( '#nowbrowsing_list' ).height( cont.height() - cont.find( '.panel_btns' ).height() - 1 );
115 | } );
116 |
117 | // 全体を作成
118 | cont.addClass( 'nowbrowsing' )
119 | .html( OutputTPL( 'nowbrowsing', {} ) );
120 |
121 | cp.SetTitle( i18nGetMessage( 'i18n_0029' ), false );
122 |
123 | nowbrowsing_list = $( '#nowbrowsing_list' );
124 |
125 | ////////////////////////////////////////
126 | // タブの更新イベントでリスト更新
127 | ////////////////////////////////////////
128 | chrome.tabs.onUpdated.addListener( ListMake );
129 | chrome.tabs.onRemoved.addListener( ListMake );
130 |
131 | ////////////////////////////////////////
132 | // 更新ボタンクリック
133 | ////////////////////////////////////////
134 | $( '#nowbrowsing_reload' ).click( function( e ) {
135 | // disabledなら処理しない
136 | if ( $( this ).hasClass( 'disabled' ) )
137 | {
138 | return;
139 | }
140 |
141 | cont.trigger( 'reload_timer' );
142 | ListMake();
143 | } );
144 |
145 | // リスト部作成処理
146 | cont.trigger( 'reload_timer' );
147 | ListMake();
148 | };
149 |
150 | ////////////////////////////////////////////////////////////
151 | // 終了処理
152 | ////////////////////////////////////////////////////////////
153 | this.stop = function() {
154 | chrome.tabs.onUpdated.removeListener( ListMake );
155 | chrome.tabs.onRemoved.removeListener( ListMake );
156 | };
157 | }
158 |
--------------------------------------------------------------------------------
/js/contents/rsslist.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | ////////////////////////////////////////////////////////////////////////////////
4 | // RSSパネル一覧
5 | ////////////////////////////////////////////////////////////////////////////////
6 | Contents.rsslist = function( cp )
7 | {
8 | var p = $( '#' + cp.id );
9 | var cont = p.find( 'div.contents' );
10 | var rsslist_list;
11 | var scrollPos = null;
12 |
13 | cp.SetIcon( 'icon-feed' );
14 |
15 | ////////////////////////////////////////////////////////////
16 | // リスト部作成
17 | ////////////////////////////////////////////////////////////
18 | var ListMake = function( type ) {
19 | cont.activity( { color: '#ffffff' } );
20 |
21 | rsslist_list.html( OutputTPL( 'rsslist_list', { items: g_cmn.rss_panel } ) )
22 | .scrollTop( 0 );
23 |
24 | ////////////////////////////////////////
25 | // タイトルクリック
26 | ////////////////////////////////////////
27 | rsslist_list.find( 'div.item .title span' ).click( function( e ) {
28 | // disabledなら処理しない
29 | if ( $( this ).hasClass( 'disabled' ) )
30 | {
31 | return;
32 | }
33 |
34 | var item = $( this ).parent().parent();
35 | var id = item.attr( 'id' );
36 |
37 | // 既に開かれている
38 | if ( GetPanel( 'panel_' + id ) != null )
39 | {
40 | SetFront( $( '#panel_' + id ) );
41 | }
42 | else
43 | {
44 | var _cp = new CPanel( null, null, 320, 360, id );
45 | _cp.SetType( 'rss' );
46 | _cp.SetParam( g_cmn.rss_panel[id].param );
47 | _cp.Start();
48 | }
49 |
50 | e.stopPropagation();
51 | } );
52 |
53 | ////////////////////////////////////////
54 | // 削除ボタンクリック
55 | ////////////////////////////////////////
56 | rsslist_list.find( 'div.item .removebtn' ).click( function( e ) {
57 | // disabledなら処理しない
58 | if ( $( this ).hasClass( 'disabled' ) )
59 | {
60 | return;
61 | }
62 |
63 | if ( confirm( i18nGetMessage( 'i18n_0224' ) ) )
64 | {
65 | var item = $( this ).parent().parent();
66 | var id = item.attr( 'id' );
67 |
68 | // 開いている場合は閉じる
69 | if ( GetPanel( 'panel_' + id ) != null )
70 | {
71 | $( '#panel_' + id ).find( '.close' ).trigger( 'click', [false] );
72 | }
73 |
74 | delete g_cmn.rss_panel[id];
75 | ListMake();
76 | }
77 |
78 | e.stopPropagation();
79 | } );
80 |
81 | cont.trigger( 'contents_resize' );
82 |
83 | cont.activity( false );
84 | };
85 |
86 | ////////////////////////////////////////////////////////////
87 | // 開始処理
88 | ////////////////////////////////////////////////////////////
89 | this.start = function() {
90 | ////////////////////////////////////////
91 | // 最小化/設定切替時のスクロール位置
92 | // 保存/復元
93 | ////////////////////////////////////////
94 | cont.on( 'contents_scrollsave', function( e, type ) {
95 | // 保存
96 | if ( type == 0 )
97 | {
98 | if ( scrollPos == null )
99 | {
100 | scrollPos = rsslist_list.scrollTop();
101 | }
102 | }
103 | // 復元
104 | else
105 | {
106 | if ( scrollPos != null )
107 | {
108 | rsslist_list.scrollTop( scrollPos );
109 | scrollPos = null;
110 | }
111 | }
112 | } );
113 |
114 | ////////////////////////////////////////
115 | // リサイズ処理
116 | ////////////////////////////////////////
117 | cont.on( 'contents_resize', function() {
118 | $( '#rsslist_list' ).height( cont.height() - cont.find( '.panel_btns' ).height() - 1 );
119 | } );
120 |
121 | // 全体を作成
122 | cont.addClass( 'rsslist' )
123 | .html( OutputTPL( 'rsslist', {} ) );
124 |
125 | cp.SetTitle( i18nGetMessage( 'i18n_0032' ), false );
126 |
127 | rsslist_list = $( '#rsslist_list' );
128 |
129 | ////////////////////////////////////////
130 | // 新規作成ボタンクリック
131 | ////////////////////////////////////////
132 | $( '#rsslist_create' ).click( function( e ) {
133 | // disabledなら処理しない
134 | if ( $( this ).hasClass( 'disabled' ) )
135 | {
136 | return;
137 | }
138 |
139 | var _cp = new CPanel( null, null, 320, 360 );
140 | _cp.SetType( 'rss' );
141 | _cp.SetParam( { title: 'RSS', urls: [], reload_time: 15, count: 10 } );
142 | _cp.Start( function() {
143 | $( '#' + _cp.id ).find( 'div.titlebar' ).find( '.setting' ).trigger( 'click' );
144 |
145 | var _id = _cp.id.replace( /^panel_/, '' );
146 | g_cmn.rss_panel[_id] = {
147 | id: _id,
148 | param: _cp.param,
149 | };
150 |
151 | ListMake();
152 | } );
153 |
154 | e.stopPropagation();
155 | } );
156 |
157 | ////////////////////////////////////////
158 | // 更新ボタンクリック
159 | ////////////////////////////////////////
160 | $( '#rsslist_reload' ).click( function( e ) {
161 | // disabledなら処理しない
162 | if ( $( this ).hasClass( 'disabled' ) )
163 | {
164 | return;
165 | }
166 |
167 | ListMake();
168 | } );
169 |
170 | // リスト部作成処理
171 | ListMake();
172 | };
173 |
174 | ////////////////////////////////////////////////////////////
175 | // 終了処理
176 | ////////////////////////////////////////////////////////////
177 | this.stop = function() {
178 | };
179 | }
180 |
--------------------------------------------------------------------------------
/js/contents/searchbox.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | ////////////////////////////////////////////////////////////////////////////////
4 | // 検索
5 | ////////////////////////////////////////////////////////////////////////////////
6 | Contents.searchbox = function( cp )
7 | {
8 | var p = $( '#' + cp.id );
9 | var cont = p.find( 'div.contents' );
10 |
11 | cp.SetIcon( 'icon-search' );
12 |
13 | ////////////////////////////////////////////////////////////
14 | // プルダウンメニューを作成
15 | ////////////////////////////////////////////////////////////
16 | function MakePullDown()
17 | {
18 | var s = '';
19 |
20 | if ( g_cmn.account[cp.param['account_id']].notsave.saved_search )
21 | {
22 | for ( var i = 0, _len = g_cmn.account[cp.param['account_id']].notsave.saved_search.length ; i < _len ; i++ )
23 | {
24 | s += '
' + escapeHTML( g_cmn.account[cp.param['account_id']].notsave.saved_search[i] ) + '
';
25 | }
26 | }
27 |
28 | var pulldown = $( '#searchbox_box' ).find( '.pulldown' );
29 |
30 | pulldown.html( s );
31 |
32 | if ( s == '' )
33 | {
34 | pulldown.hide();
35 | }
36 | }
37 |
38 | ////////////////////////////////////////////////////////////
39 | // 開始処理
40 | ////////////////////////////////////////////////////////////
41 | this.start = function() {
42 | cont.addClass( 'searchbox' )
43 | .html( OutputTPL( 'searchbox', {} ) );
44 |
45 | cp.SetTitle( i18nGetMessage( 'i18n_0206' ), false );
46 |
47 | $( '#searchbox_box' ).find( '.btn' ).addClass( 'disabled' );
48 |
49 | ////////////////////////////////////////
50 | // リサイズ処理
51 | ////////////////////////////////////////
52 | cont.on( 'contents_resize', function() {
53 | $( '#searchbox_text' ).width( p.width() - 34 - $( '#search' ).outerWidth() - $( '#usersearch' ).outerWidth() );
54 | $( '#searchbox_box' ).find( '.pulldown' ).width( $( '#searchbox_text' ).width() );
55 | } );
56 |
57 | cont.trigger( 'contents_resize' );
58 |
59 | ////////////////////////////////////////
60 | // アカウント選択変更
61 | ////////////////////////////////////////
62 | cont.on( 'account_changed', function() {
63 | MakePullDown();
64 | } );
65 |
66 | ////////////////////////////////////////
67 | // アカウント情報更新
68 | ////////////////////////////////////////
69 | cont.on( 'account_update', function() {
70 | // アカウントが0件の場合はパネルを閉じる
71 | if ( AccountCount() == 0 )
72 | {
73 | // 検索パネルを閉じる
74 | p.find( '.close' ).trigger( 'click', [false] );
75 | return;
76 | }
77 | else
78 | {
79 | AccountSelectMake( cp );
80 | cont.trigger( 'account_changed' );
81 | }
82 | } );
83 |
84 | cont.trigger( 'account_update' );
85 |
86 | ////////////////////////////////////////
87 | // 検索ボタンクリック処理
88 | ////////////////////////////////////////
89 | $( '#search' ).click( function( e ) {
90 | // disabledなら処理しない
91 | if ( $( this ).hasClass( 'disabled' ) )
92 | {
93 | return;
94 | }
95 |
96 | // ツイートのURLの場合、そのツイートをパネルで開く
97 | if ( $( '#searchbox_text' ).val().match( /https:\/\/twitter\.com\/([0-9a-zA-Z_]+)\/status\/(\d+)/ ) )
98 | {
99 | var screen_name = RegExp.$1;
100 | var status_id = RegExp.$2;
101 |
102 | var _cp = new CPanel( null, null, 360, 240 );
103 | _cp.SetType( 'timeline' );
104 | _cp.SetParam( {
105 | account_id: cp.param['account_id'],
106 | timeline_type: 'perma',
107 | screen_name: screen_name,
108 | status_id: status_id,
109 | reload_time: g_cmn.cmn_param['reload_time'],
110 | } );
111 | _cp.Start();
112 |
113 | return false;
114 | }
115 |
116 | OpenSearchResult( $( '#searchbox_text' ).val(), cp.param['account_id'] );
117 | e.stopPropagation();
118 | } );
119 |
120 | ////////////////////////////////////////
121 | // ユーザ検索ボタンクリック処理
122 | ////////////////////////////////////////
123 | $( '#usersearch' ).click( function( e ) {
124 | // disabledなら処理しない
125 | if ( $( this ).hasClass( 'disabled' ) )
126 | {
127 | return;
128 | }
129 |
130 | var _cp = new CPanel( null, null, 320, 300 );
131 | _cp.SetType( 'usersearch' );
132 | _cp.SetParam( {
133 | account_id: cp.param['account_id'],
134 | q: $( '#searchbox_text' ).val(),
135 | } );
136 | _cp.Start();
137 |
138 | e.stopPropagation();
139 | } );
140 |
141 | ////////////////////////////////////////
142 | // 入力文字数によるボタン制御
143 | ////////////////////////////////////////
144 | $( '#searchbox_text' ).on( 'keyup change', function() {
145 | var slen = $( this ).val().length;
146 |
147 | if ( slen > 0 )
148 | {
149 | $( '#searchbox_box' ).find( '.btn' ).removeClass( 'disabled' );
150 | }
151 | else
152 | {
153 | $( '#searchbox_box' ).find( '.btn' ).addClass( 'disabled' );
154 | }
155 | } );
156 |
157 | $( '#searchbox_text' ).focus();
158 |
159 | ////////////////////////////////////////
160 | // テキストボックスクリック
161 | ////////////////////////////////////////
162 | $( '#searchbox_text' ).click( function( e ) {
163 | var pulldown = $( this ).parent().find( '.pulldown' );
164 |
165 | if ( pulldown.css( 'display' ) == 'none' )
166 | {
167 | if ( pulldown.find( 'div.item' ).length )
168 | {
169 | pulldown.show();
170 | }
171 | }
172 | else
173 | {
174 | pulldown.hide();
175 | }
176 |
177 | e.stopPropagation();
178 | } );
179 |
180 | ////////////////////////////////////////
181 | // プルダウン選択
182 | ////////////////////////////////////////
183 | $( '#searchbox_box' ).find( 'div.pulldown' ).on( 'click', '> div.item', function( e ) {
184 | $( '#searchbox_text' ).val( $( this ).text() )
185 | .trigger( 'keyup' )
186 | .focus();
187 |
188 | $( this ).parent().hide();
189 |
190 | e.stopPropagation();
191 | } );
192 |
193 | ////////////////////////////////////////
194 | // Enterで検索実行
195 | ////////////////////////////////////////
196 | $( '#searchbox_text' ).keypress( function( e ) {
197 | if ( e.keyCode == 13 )
198 | {
199 | $( '#search' ).trigger( 'click' );
200 | }
201 | } );
202 | };
203 |
204 | ////////////////////////////////////////////////////////////
205 | // 終了処理
206 | ////////////////////////////////////////////////////////////
207 | this.stop = function() {
208 | };
209 | }
210 |
--------------------------------------------------------------------------------
/js/contents/saved_search.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | ////////////////////////////////////////////////////////////////////////////////
4 | // 検索メモ一覧
5 | ////////////////////////////////////////////////////////////////////////////////
6 | Contents.saved_search = function( cp )
7 | {
8 | var p = $( '#' + cp.id );
9 | var cont = p.find( 'div.contents' );
10 | var scrollPos = null;
11 |
12 | cp.SetIcon( 'icon-search' );
13 |
14 | ////////////////////////////////////////////////////////////
15 | // リスト部作成
16 | ////////////////////////////////////////////////////////////
17 | var ListMake = function() {
18 | var param = {
19 | type: 'GET',
20 | url: ApiUrl( '1.1' ) + 'saved_searches/list.json',
21 | data: {
22 | },
23 | };
24 |
25 | var items = new Array();
26 |
27 | cont.activity( { color: '#ffffff' } );
28 |
29 | SendRequest(
30 | {
31 | action: 'oauth_send',
32 | acsToken: g_cmn.account[cp.param['account_id']]['accessToken'],
33 | acsSecret: g_cmn.account[cp.param['account_id']]['accessSecret'],
34 | param: param,
35 | id: cp.param['account_id'],
36 | },
37 | function( res )
38 | {
39 | g_cmn.account[cp.param['account_id']].notsave.saved_search = [];
40 |
41 | if ( res.status == 200 )
42 | {
43 | for ( var i = 0, _len = res.json.length ; i < _len ; i++ )
44 | {
45 | g_cmn.account[cp.param['account_id']].notsave.saved_search.push( res.json[i].query );
46 |
47 | items.push( {
48 | id: res.json[i].id_str,
49 | query: escapeHTML( res.json[i].query ),
50 | } );
51 | }
52 |
53 | cont.find( '.saved_search_list' ).html( OutputTPL( 'saved_search_list', { items: items } ) );
54 |
55 | // 検索パネルを開いている場合はプルダウン更新
56 | var pid = IsUnique( 'searchbox' );
57 |
58 | if ( pid != null )
59 | {
60 | $( '#' + pid ).find( 'div.contents' ).trigger( 'account_changed' );
61 | }
62 |
63 | cont.trigger( 'contents_resize' );
64 |
65 | ////////////////////////////////////////
66 | // 削除ボタンクリック処理
67 | ////////////////////////////////////////
68 | cont.find( '.saved_search_list' ).find( 'div.item .delbtn' ).click( function( e ) {
69 | // disabledなら処理しない
70 | if ( $( this ).hasClass( 'disabled' ) )
71 | {
72 | return;
73 | }
74 |
75 | var query = $( this ).parent().parent().find( '.query' );
76 |
77 | var conf = confirm( i18nGetMessage( 'i18n_0185', [query.attr( 'query' )] ) );
78 |
79 | if ( conf )
80 | {
81 | var param = {
82 | type: 'POST',
83 | url: ApiUrl( '1.1' ) + 'saved_searches/destroy/' + query.attr( 'sid' ) + '.json',
84 | data: {
85 | },
86 | };
87 |
88 | Blackout( true );
89 | $( '#blackout' ).activity( { color: '#808080', width: 8, length: 14 } );
90 |
91 | SendRequest(
92 | {
93 | action: 'oauth_send',
94 | acsToken: g_cmn.account[cp.param['account_id']]['accessToken'],
95 | acsSecret: g_cmn.account[cp.param['account_id']]['accessSecret'],
96 | param: param,
97 | id: cp.param['account_id']
98 | },
99 | function( res )
100 | {
101 | if ( res.status == 200 )
102 | {
103 | ListMake();
104 | }
105 | else
106 | {
107 | ApiError( i18nGetMessage( 'i18n_0225' ), res );
108 | }
109 |
110 | Blackout( false );
111 | $( '#blackout' ).activity( false );
112 | }
113 | );
114 | }
115 |
116 | e.stopPropagation();
117 | } );
118 | }
119 | else
120 | {
121 | ApiError( i18nGetMessage( 'i18n_0209' ), res );
122 | }
123 |
124 | $( 'panel' ).find( 'div.contents' ).trigger( 'api_remaining_update', [cp.param['account_id']] );
125 | cont.activity( false );
126 | }
127 | );
128 | };
129 |
130 | ////////////////////////////////////////////////////////////
131 | // 開始処理
132 | ////////////////////////////////////////////////////////////
133 | this.start = function() {
134 | ////////////////////////////////////////
135 | // 最小化/設定切替時のスクロール位置
136 | // 保存/復元
137 | ////////////////////////////////////////
138 | cont.on( 'contents_scrollsave', function( e, type ) {
139 | // 保存
140 | if ( type == 0 )
141 | {
142 | if ( scrollPos == null )
143 | {
144 | scrollPos = cont.find( '.saved_search_list' ).scrollTop();
145 | }
146 | }
147 | // 復元
148 | else
149 | {
150 | if ( scrollPos != null )
151 | {
152 | cont.find( '.saved_search_list' ).scrollTop( scrollPos );
153 | scrollPos = null;
154 | }
155 | }
156 | } );
157 |
158 | ////////////////////////////////////////
159 | // リサイズ処理
160 | ////////////////////////////////////////
161 | cont.on( 'contents_resize', function() {
162 | cont.find( '.saved_search_list' ).height( cont.height() - cont.find( '.panel_btns' ).height() - 1 );
163 | } );
164 |
165 | ////////////////////////////////////////
166 | // このパネルを開いたアカウントが
167 | // 削除された場合
168 | ////////////////////////////////////////
169 | var AccountAliveCheck = function() {
170 | if ( g_cmn.account[cp.param['account_id']] == undefined )
171 | {
172 | // パネルを閉じる
173 | p.find( '.close' ).trigger( 'click', [false] );
174 | return false;
175 | }
176 |
177 | return true;
178 | };
179 |
180 | ////////////////////////////////////////
181 | // アカウント情報更新
182 | ////////////////////////////////////////
183 | cont.on( 'account_update', function() {
184 | AccountAliveCheck();
185 | } );
186 |
187 | if ( !AccountAliveCheck() )
188 | {
189 | return;
190 | }
191 |
192 | // 全体を作成
193 | cont.addClass( 'saved_search' )
194 | .html( OutputTPL( 'saved_search', {} ) );
195 |
196 | cp.SetTitle( g_cmn.account[cp.param['account_id']].screen_name + ' ' + i18nGetMessage( 'i18n_0207' ), false );
197 |
198 | ////////////////////////////////////////
199 | // 更新ボタンクリック
200 | ////////////////////////////////////////
201 | cont.find( '.panel_btns' ).find( '.saved_search_reload' ).click( function( e ) {
202 | // disabledなら処理しない
203 | if ( $( this ).hasClass( 'disabled' ) )
204 | {
205 | return;
206 | }
207 |
208 | ListMake();
209 | } );
210 |
211 | // リスト部作成処理
212 | ListMake();
213 | };
214 |
215 | ////////////////////////////////////////////////////////////
216 | // 終了処理
217 | ////////////////////////////////////////////////////////////
218 | this.stop = function() {
219 | };
220 | }
221 |
--------------------------------------------------------------------------------
/js/lib/sha1.js:
--------------------------------------------------------------------------------
1 | /*
2 | * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
3 | * in FIPS PUB 180-1
4 | * Version 2.1a Copyright Paul Johnston 2000 - 2002.
5 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
6 | * Distributed under the BSD License
7 | * See http://pajhome.org.uk/crypt/md5 for details.
8 | */
9 |
10 | /*
11 | * Configurable variables. You may need to tweak these to be compatible with
12 | * the server-side, but the defaults work in most cases.
13 | */
14 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
15 | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
16 | var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
17 |
18 | /*
19 | * These are the functions you'll usually want to call
20 | * They take string arguments and return either hex or base-64 encoded strings
21 | */
22 | function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
23 | function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
24 | function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
25 | function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
26 | function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
27 | function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
28 |
29 | /*
30 | * Perform a simple self-test to see if the VM is working
31 | */
32 | function sha1_vm_test()
33 | {
34 | return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
35 | }
36 |
37 | /*
38 | * Calculate the SHA-1 of an array of big-endian words, and a bit length
39 | */
40 | function core_sha1(x, len)
41 | {
42 | /* append padding */
43 | x[len >> 5] |= 0x80 << (24 - len % 32);
44 | x[((len + 64 >> 9) << 4) + 15] = len;
45 |
46 | var w = Array(80);
47 | var a = 1732584193;
48 | var b = -271733879;
49 | var c = -1732584194;
50 | var d = 271733878;
51 | var e = -1009589776;
52 |
53 | for(var i = 0; i < x.length; i += 16)
54 | {
55 | var olda = a;
56 | var oldb = b;
57 | var oldc = c;
58 | var oldd = d;
59 | var olde = e;
60 |
61 | for(var j = 0; j < 80; j++)
62 | {
63 | if(j < 16) w[j] = x[i + j];
64 | else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
65 | var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
66 | safe_add(safe_add(e, w[j]), sha1_kt(j)));
67 | e = d;
68 | d = c;
69 | c = rol(b, 30);
70 | b = a;
71 | a = t;
72 | }
73 |
74 | a = safe_add(a, olda);
75 | b = safe_add(b, oldb);
76 | c = safe_add(c, oldc);
77 | d = safe_add(d, oldd);
78 | e = safe_add(e, olde);
79 | }
80 | return Array(a, b, c, d, e);
81 |
82 | }
83 |
84 | /*
85 | * Perform the appropriate triplet combination function for the current
86 | * iteration
87 | */
88 | function sha1_ft(t, b, c, d)
89 | {
90 | if(t < 20) return (b & c) | ((~b) & d);
91 | if(t < 40) return b ^ c ^ d;
92 | if(t < 60) return (b & c) | (b & d) | (c & d);
93 | return b ^ c ^ d;
94 | }
95 |
96 | /*
97 | * Determine the appropriate additive constant for the current iteration
98 | */
99 | function sha1_kt(t)
100 | {
101 | return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
102 | (t < 60) ? -1894007588 : -899497514;
103 | }
104 |
105 | /*
106 | * Calculate the HMAC-SHA1 of a key and some data
107 | */
108 | function core_hmac_sha1(key, data)
109 | {
110 | var bkey = str2binb(key);
111 | if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
112 |
113 | var ipad = Array(16), opad = Array(16);
114 | for(var i = 0; i < 16; i++)
115 | {
116 | ipad[i] = bkey[i] ^ 0x36363636;
117 | opad[i] = bkey[i] ^ 0x5C5C5C5C;
118 | }
119 |
120 | var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
121 | return core_sha1(opad.concat(hash), 512 + 160);
122 | }
123 |
124 | /*
125 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally
126 | * to work around bugs in some JS interpreters.
127 | */
128 | function safe_add(x, y)
129 | {
130 | var lsw = (x & 0xFFFF) + (y & 0xFFFF);
131 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
132 | return (msw << 16) | (lsw & 0xFFFF);
133 | }
134 |
135 | /*
136 | * Bitwise rotate a 32-bit number to the left.
137 | */
138 | function rol(num, cnt)
139 | {
140 | return (num << cnt) | (num >>> (32 - cnt));
141 | }
142 |
143 | /*
144 | * Convert an 8-bit or 16-bit string to an array of big-endian words
145 | * In 8-bit function, characters >255 have their hi-byte silently ignored.
146 | */
147 | function str2binb(str)
148 | {
149 | var bin = Array();
150 | var mask = (1 << chrsz) - 1;
151 | for(var i = 0; i < str.length * chrsz; i += chrsz)
152 | bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
153 | return bin;
154 | }
155 |
156 | /*
157 | * Convert an array of big-endian words to a string
158 | */
159 | function binb2str(bin)
160 | {
161 | var str = "";
162 | var mask = (1 << chrsz) - 1;
163 | for(var i = 0; i < bin.length * 32; i += chrsz)
164 | str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
165 | return str;
166 | }
167 |
168 | /*
169 | * Convert an array of big-endian words to a hex string.
170 | */
171 | function binb2hex(binarray)
172 | {
173 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
174 | var str = "";
175 | for(var i = 0; i < binarray.length * 4; i++)
176 | {
177 | str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
178 | hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
179 | }
180 | return str;
181 | }
182 |
183 | /*
184 | * Convert an array of big-endian words to a base-64 string
185 | */
186 | function binb2b64(binarray)
187 | {
188 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
189 | var str = "";
190 | for(var i = 0; i < binarray.length * 4; i += 3)
191 | {
192 | var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
193 | | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
194 | | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
195 | for(var j = 0; j < 4; j++)
196 | {
197 | if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
198 | else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
199 | }
200 | }
201 | return str;
202 | }
203 |
--------------------------------------------------------------------------------
/js/contents/impexp.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | // インポート/エクスポート
3 | ////////////////////////////////////////////////////////////////////////////////
4 | Contents.impexp = function( cp )
5 | {
6 | var p = $( '#' + cp.id );
7 | var cont = p.find( 'div.contents' );
8 | var filesystem;
9 | var exportfile = 'kurotwi.data.txt';
10 |
11 | if ( window.webkitRequestFileSystem )
12 | {
13 | webkitRequestFileSystem( TEMPORARY, 1024*1024*1, function( fs ) {
14 | filesystem = fs;
15 | } );
16 | }
17 |
18 | cp.SetIcon( 'icon-folder-open' );
19 |
20 | ////////////////////////////////////////////////////////////
21 | // 一時ファイル削除
22 | ////////////////////////////////////////////////////////////
23 | function DeleteTMPFile( name, callback, stopflg )
24 | {
25 | if ( filesystem )
26 | {
27 | filesystem.root.getFile( name, {}, function( entry ) {
28 | entry.remove( callback, function( e ) {
29 | console.log( 'remove' );
30 | console.log( e );
31 | if ( !stopflg )
32 | {
33 | MessageBox( i18nGetMessage( 'i18n_0347' ) );
34 | }
35 | } );
36 | }, function( e ) {
37 | if ( e.name != 'NotFoundError' )
38 | {
39 | console.log( 'getFile' );
40 | console.log( e );
41 |
42 | if ( !stopflg )
43 | {
44 | MessageBox( i18nGetMessage( 'i18n_0347' ) );
45 | }
46 | }
47 | else
48 | {
49 | callback();
50 | }
51 | } );
52 | }
53 | }
54 |
55 | ////////////////////////////////////////////////////////////
56 | // 開始処理
57 | ////////////////////////////////////////////////////////////
58 | this.start = function() {
59 | cont.addClass( 'impexp' )
60 | .html( OutputTPL( 'impexp', {} ) );
61 |
62 | cp.SetTitle( i18nGetMessage( 'i18n_0052' ) + '/' + i18nGetMessage( 'i18n_0053' ), false );
63 |
64 | $( '#import .item .btn.exec' ).addClass( 'disabled' );
65 |
66 | if ( !window.webkitRequestFileSystem )
67 | {
68 | MessageBox( 'Chrome only' );
69 | p.find( '.close' ).trigger( 'click', [false] );
70 | return false;
71 | }
72 |
73 | ////////////////////////////////////////
74 | // リサイズ処理
75 | ////////////////////////////////////////
76 | cont.bind( 'contents_resize', function() {
77 | } );
78 |
79 | cont.trigger( 'contents_resize' );
80 |
81 | ////////////////////////////////////////
82 | // インポート実行ボタンクリック処理
83 | ////////////////////////////////////////
84 | $( '#import .item .btn.exec' ).click( function( e ) {
85 | // disabedなら処理しない
86 | if ( $( this ).hasClass( 'disabled' ) )
87 | {
88 | return;
89 | }
90 |
91 | var file = $( '#importfile_input' )[0].files[0];
92 |
93 | if ( file.type != 'text/plain' )
94 | {
95 | MessageBox( i18nGetMessage( 'i18n_0348' ) );
96 | return;
97 | }
98 |
99 | var reader = new FileReader();
100 |
101 | reader.onload = ( function( thefile ) {
102 | return function( e ) {
103 | try {
104 | var _g_cmn = JSON.parse( decodeURIComponent_space( e.target.result ) );
105 | }
106 | catch( e ) {
107 | console.log( e );
108 | MessageBox( i18nGetMessage( 'i18n_0348' ) );
109 | return;
110 | }
111 |
112 | if ( _g_cmn.current_version == undefined )
113 | {
114 | MessageBox( i18nGetMessage( 'i18n_0348' ) );
115 | return;
116 | }
117 |
118 | // バージョンアップと誤認しないようにバージョンを差し替え
119 | _g_cmn.current_version = g_cmn.current_version;
120 |
121 | try {
122 | var text = JSON.stringify( _g_cmn );
123 | text = encodeURIComponent( text );
124 | }
125 | catch( e ) {
126 | console.log( e );
127 | MessageBox( i18nGetMessage( 'i18n_0348' ) );
128 | return;
129 | }
130 |
131 | setUserInfo( 'g_cmn_V1', text );
132 | g_saveend = false;
133 | chrome.tabs.reload();
134 | };
135 | } )( file );
136 |
137 | reader.readAsText( file );
138 |
139 | e.stopPropagation();
140 | } );
141 |
142 | ////////////////////////////////////////
143 | // エクスポート実行ボタンクリック処理
144 | ////////////////////////////////////////
145 | $( '#export .item .btn.exec' ).click( function( e ) {
146 | // disabedなら処理しない
147 | if ( $( this ).hasClass( 'disabled' ) )
148 | {
149 | return;
150 | }
151 |
152 | var CreateNewFile = function() {
153 | filesystem.root.getFile( exportfile, { 'create': true }, function( entry ) {
154 | entry.createWriter( function( writer ) {
155 | writer.onwriteend = function() {
156 | $( '
' )[0].click();
157 | };
158 |
159 | var lines = SaveDataText();
160 |
161 | var blob = new Blob( [ lines ], { type: 'text.plain' } );
162 |
163 | writer.write( blob );
164 | }, function( e ) {
165 | console.log( 'createWriter' );
166 | console.log( e );
167 | MessageBox( i18nGetMessage( 'i18n_0347' ) );
168 | } );
169 | }, function( e ) {
170 | console.log( 'getFile' );
171 | console.log( e );
172 | MessageBox( i18nGetMessage( 'i18n_0347' ) );
173 | } );
174 | };
175 |
176 | DeleteTMPFile( exportfile, CreateNewFile );
177 |
178 | e.stopPropagation();
179 | } );
180 |
181 | ////////////////////////////////////////
182 | // ファイル選択ボタンクリック処理
183 | ////////////////////////////////////////
184 | $( '#importselectbtn' ).click( function( e ) {
185 | // disabledなら処理しない
186 | if ( $( this ).hasClass( 'disabled' ) )
187 | {
188 | return;
189 | }
190 |
191 | $( '#importfile_input' ).click();
192 | e.stopPropagation();
193 | } );
194 |
195 | ////////////////////////////////////////
196 | // ファイル選択変更時の処理
197 | ////////////////////////////////////////
198 | $( '#importfile_input' ).change( function( e ) {
199 | if ( $( '#importfile_input' )[0].files.length == 1 )
200 | {
201 | $( '#import .item .btn.exec' ).removeClass( 'disabled' );
202 | $( '#importfile' ).html( $( '#importfile_input' )[0].files[0].name );
203 | }
204 | else
205 | {
206 | $( '#import .item .btn.exec' ).addClass( 'disabled' );
207 | $( '#importfile' ).html( i18nGetMessage( 'i18n_0119' ) );
208 | }
209 |
210 | e.stopPropagation();
211 | } );
212 | };
213 |
214 | ////////////////////////////////////////////////////////////
215 | // 終了処理
216 | ////////////////////////////////////////////////////////////
217 | this.stop = function() {
218 | DeleteTMPFile( exportfile, function() {}, true );
219 | };
220 | }
221 |
--------------------------------------------------------------------------------
/js/contents/dmbox.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | ////////////////////////////////////////////////////////////////////////////////
4 | // DM
5 | ////////////////////////////////////////////////////////////////////////////////
6 | Contents.dmbox = function( cp )
7 | {
8 | var p = $( '#' + cp.id );
9 | var cont = p.find( 'div.contents' );
10 |
11 | cp.SetIcon( 'icon-envelop' );
12 |
13 | ////////////////////////////////////////////////////////////
14 | // 開始処理
15 | ////////////////////////////////////////////////////////////
16 | this.start = function() {
17 | cp.param.maxlen = 10000;
18 |
19 | cont.addClass( 'dmbox' )
20 | .html( OutputTPL( 'dmbox', { maxlen: cp.param['maxlen'] } ) );
21 |
22 | $( '#dmbox_cnt' ).hide();
23 |
24 | cp.SetTitle( i18nGetMessage( 'i18n_0149', [cp.param.screen_name] ), false );
25 |
26 | // 送信ボタンのツールチップを設定に合わせる
27 | var _tips = new Array( 'Ctrl+Enter', 'Shift+Enter', 'Enter' );
28 | $( '#dmsend' ).attr( 'tooltip', i18nGetMessage( 'i18n_0250' ) + '(' + _tips[g_cmn.cmn_param.tweetkey] + ')' );
29 |
30 | $( '#dmbox_text' ).focus();
31 |
32 | ////////////////////////////////////////
33 | // リサイズ処理
34 | ////////////////////////////////////////
35 | cont.on( 'contents_resize', function() {
36 | $( '#dmbox_text' ).width( p.width() - 24 );
37 | $( '#dmbox_box' ).find( 'div' ).first().width( p.width() - 12 );
38 |
39 | var acc_h = cont.find( '.account_select' ).outerHeight();
40 |
41 | var btn_h = $( '#dmbox_btn' ).parent().outerHeight();
42 |
43 | $( '#dmbox_box' ).height( cont.outerHeight() - acc_h - 12 );
44 | $( '#dmbox_text' ).height( $( '#dmbox_box' ).outerHeight() - btn_h - 24 );
45 | } );
46 |
47 | cont.trigger( 'contents_resize' );
48 |
49 | ////////////////////////////////////////
50 | // アカウント情報更新
51 | ////////////////////////////////////////
52 | cont.on( 'account_update', function() {
53 | // アカウントが0件の場合はパネルを閉じる
54 | if ( AccountCount() == 0 )
55 | {
56 | // ツイートパネルを閉じる
57 | p.find( '.close' ).trigger( 'click', [false] );
58 | return;
59 | }
60 | else
61 | {
62 | AccountSelectMake( cp );
63 | }
64 | } );
65 |
66 | cont.trigger( 'account_update' );
67 |
68 | ////////////////////////////////////////
69 | // 送信ボタンクリック処理
70 | ////////////////////////////////////////
71 | $( '#dmsend' ).click( function( e ) {
72 | // disabledなら処理しない
73 | if ( $( this ).hasClass( 'disabled' ) )
74 | {
75 | return;
76 | }
77 |
78 | // 文字数チェック
79 | var val = dmbox_text.val();
80 | var urls = twttr.txt.extractUrls( val );
81 |
82 | for ( var i = 0, _len = urls.length ; i < _len ; i++ )
83 | {
84 | val = val.replace( urls[i], tco );
85 | }
86 |
87 | var slen = val.length;
88 |
89 | if ( slen > cp.param['maxlen'] )
90 | {
91 | MessageBox( i18nGetMessage( 'i18n_0356', [slen, cp.param['maxlen']] ) );
92 | return;
93 | }
94 |
95 | $( this ).addClass( 'disabled' );
96 |
97 | var data = {};
98 | var status = '';
99 |
100 | status += $( '#dmbox_text' ).val();
101 |
102 | var conf = confirm( i18nGetMessage( 'i18n_0150', [g_cmn.account[cp.param['account_id']]['screen_name'],cp.param['screen_name']] ) );
103 |
104 | if ( !conf )
105 | {
106 | $( this ).removeClass( 'disabled' );
107 | e.stopPropagation();
108 | return;
109 | }
110 |
111 | data['text'] = status;
112 | data['screen_name'] = cp.param['screen_name'];
113 |
114 | var param = {
115 | type: 'POST',
116 | url: ApiUrl( '1.1' ) + 'direct_messages/new.json',
117 | data: data,
118 | };
119 |
120 | Blackout( true, false );
121 | $( '#blackout' ).activity( { color: '#808080', width: 8, length: 14 } );
122 |
123 | SendRequest(
124 | {
125 | action: 'oauth_send',
126 | acsToken: g_cmn.account[cp.param['account_id']]['accessToken'],
127 | acsSecret: g_cmn.account[cp.param['account_id']]['accessSecret'],
128 | param: param,
129 | id: cp.param['account_id']
130 | },
131 | function( res )
132 | {
133 | if ( res.status == 200 )
134 | {
135 | // テキストボックスを空にする
136 | $( '#dmbox_text' ).val( '' )
137 | .trigger( 'keyup' );
138 |
139 | // ツイート数表示の更新
140 | StatusesCountUpdate( cp.param['account_id'], 1 );
141 | }
142 | else
143 | {
144 | console.log( 'status[' + res.status + ']' );
145 |
146 | $( this ).removeClass( 'disabled' );
147 |
148 | ApiError( i18nGetMessage( 'i18n_0081' ), res );
149 | }
150 |
151 | Blackout( false, false );
152 | $( '#blackout' ).activity( false );
153 | }
154 | );
155 |
156 | e.stopPropagation();
157 | } );
158 |
159 | var dmbox_text = $( '#dmbox_text' );
160 | var tco = new String( '_______________________________' ).slice( 0, 23 );
161 |
162 | ////////////////////////////////////////
163 | // 入力文字数によるボタン制御
164 | ////////////////////////////////////////
165 | $( '#dmbox_text' ).on( 'keyup change', function( e ) {
166 | var val = dmbox_text.val();
167 |
168 | var slen = val.length;
169 |
170 | var btn = $( '#dmsend' );
171 |
172 | if ( slen > 0 && slen <= cp.param['maxlen'] )
173 | {
174 | btn.removeClass( 'disabled' );
175 | }
176 | else
177 | {
178 | btn.addClass( 'disabled' );
179 | }
180 | } );
181 |
182 | ////////////////////////////////////////
183 | // キーボードショートカット
184 | ////////////////////////////////////////
185 | $( '#dmbox_text' ).keydown( function( e ) {
186 | // Enterに設定されているときは、Ctrl+Enterで改行
187 | if ( g_cmn.cmn_param.tweetkey == 2 && ( e.keyCode == 13 && e.ctrlKey == true ) )
188 | {
189 | var obj = $( this ).get( 0 );
190 | var spos = obj.selectionStart;
191 | var epos = obj.selectionEnd;
192 | var s = obj.value;
193 | var np = spos + 1;
194 | obj.value = s.substr( 0, spos ) + '\n' + s.substr( epos );
195 | obj.setSelectionRange( np, np );
196 | return false;
197 | }
198 |
199 | if ( ( g_cmn.cmn_param.tweetkey == 0 && ( e.keyCode == 13 && e.ctrlKey == true ) ) ||
200 | ( g_cmn.cmn_param.tweetkey == 1 && ( e.keyCode == 13 && e.shiftKey == true ) ) ||
201 | ( g_cmn.cmn_param.tweetkey == 2 && ( e.keyCode == 13 && e.ctrlKey == false && e.shiftKey == false ) ) )
202 | {
203 | $( '#dmsend' ).trigger( 'click' );
204 | return false;
205 | }
206 | } );
207 |
208 | // 旧DM廃止のため
209 | p.find( '.close' ).trigger( 'click', [false] );
210 | };
211 |
212 | ////////////////////////////////////////////////////////////
213 | // 終了処理
214 | ////////////////////////////////////////////////////////////
215 | this.stop = function() {
216 | };
217 | }
218 |
--------------------------------------------------------------------------------
/js/contents/api_remaining.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | ////////////////////////////////////////////////////////////////////////////////
4 | // API残数
5 | ////////////////////////////////////////////////////////////////////////////////
6 | Contents.api_remaining = function( cp )
7 | {
8 | var p = $( '#' + cp.id );
9 | var cont = p.find( 'div.contents' );
10 | var scrollPos = null;
11 |
12 | cp.SetIcon( 'icon-twitter' );
13 |
14 | // API1.1対応済み
15 | var apis = {};
16 | apis['/statuses/home_timeline'] = { title: i18nGetMessage( 'i18n_0152' ), prio: 0 };
17 | apis['/statuses/mentions_timeline'] = { title: i18nGetMessage( 'i18n_0026' ), prio: 1 };
18 | apis['/lists/statuses'] = { title: i18nGetMessage( 'i18n_0167' ), prio: 2 };
19 | apis['/statuses/user_timeline'] = { title: i18nGetMessage( 'i18n_0291' ), prio: 3 };
20 | apis['/direct_messages'] = { title: i18nGetMessage( 'i18n_0021' ), prio: 4 };
21 | apis['/search/tweets'] = { title: i18nGetMessage( 'i18n_0206' ), prio: 5 };
22 | apis['/users/show/:id'] = { title: i18nGetMessage( 'i18n_0292' ), prio: 6 };
23 | apis['/statuses/show/:id'] = { title: i18nGetMessage( 'i18n_0293' ), prio: 7 };
24 | apis['/users/search'] = { title: i18nGetMessage( 'i18n_0159' ), prio: 8 };
25 | apis['/lists/list'] = { title: i18nGetMessage( 'i18n_0294' ), prio: 9 };
26 | apis['/direct_messages/sent'] = { title: i18nGetMessage( 'i18n_0251' ), prio: 10 };
27 | apis['/favorites/list'] = { title: i18nGetMessage( 'i18n_0054' ), prio: 11 };
28 | apis['/trends/place'] = { title: i18nGetMessage( 'i18n_0095' ), prio: 12 };
29 | apis['/trends/available'] = { title: i18nGetMessage( 'i18n_0295' ), prio: 13 };
30 | apis['/saved_searches/list'] = { title: i18nGetMessage( 'i18n_0207' ), prio: 14 };
31 | apis['/users/lookup'] = { title: i18nGetMessage( 'i18n_0316' ), prio: 15 };
32 | apis['/application/rate_limit_status'] = { title: i18nGetMessage( 'i18n_0296' ), prio: 16 };
33 | apis['/blocks/ids'] = { title: i18nGetMessage( 'i18n_0318' ), prio: 17 };
34 | apis['/friends/ids'] = { title: i18nGetMessage( 'i18n_0319' ), prio: 18 };
35 | apis['/followers/ids'] = { title: i18nGetMessage( 'i18n_0320' ), prio: 19 };
36 | apis['/friendships/incoming'] = { title: i18nGetMessage( 'i18n_0321' ), prio: 20 };
37 | apis['/friendships/no_retweets/ids'] = { title: i18nGetMessage( 'i18n_0326' ), prio: 21 };
38 | apis['/mutes/users/ids'] = { title: i18nGetMessage( 'i18n_0367' ), prio: 22 };
39 | apis['/help/configuration'] = { title: i18nGetMessage( 'i18n_0297' ), prio: 23 };
40 |
41 | var apis_length = 0;
42 |
43 | for ( var api in apis )
44 | {
45 | apis_length++;
46 | }
47 |
48 | ////////////////////////////////////////////////////////////
49 | // リスト部作成
50 | ////////////////////////////////////////////////////////////
51 | var ListMake = function() {
52 | var account = g_cmn.account[cp.param['account_id']];
53 | var param = {
54 | type: 'GET',
55 | url: ApiUrl( '1.1' ) + 'application/rate_limit_status.json',
56 | data: {
57 | resources: 'account,application,blocks,direct_messages,favorites,followers,friends,friendships,geo,help,lists,saved_searches,search,statuses,trends,users,friends,followers,mutes',
58 | },
59 | };
60 |
61 | cont.activity( { color: '#ffffff' } );
62 |
63 | SendRequest(
64 | {
65 | action: 'oauth_send',
66 | acsToken: account.accessToken,
67 | acsSecret: account.accessSecret,
68 | param: param,
69 | id: cp.param['account_id']
70 | },
71 | function( res )
72 | {
73 | var items = new Array( apis_length );
74 | var dt;
75 |
76 | if ( res.status == 200 )
77 | {
78 | for ( var resource in res.json.resources )
79 | {
80 | for ( var api in res.json.resources[resource] )
81 | {
82 | if ( apis[api] != undefined )
83 | {
84 | dt = new Date();
85 | dt.setTime( res.json.resources[resource][api]['reset'] * 1000 );
86 |
87 | items[apis[api].prio] = {
88 | api: api,
89 | title: apis[api].title,
90 | remaining: res.json.resources[resource][api]['remaining'],
91 | limit: res.json.resources[resource][api]['limit'],
92 | reset: ( '00' + dt.getHours() ).slice( -2 ) + ':' +
93 | ( '00' + dt.getMinutes() ).slice( -2 ) + ':' +
94 | ( '00' + dt.getSeconds() ).slice( -2 ),
95 | per: Math.floor( res.json.resources[resource][api]['remaining'] / res.json.resources[resource][api]['limit'] * 100 ),
96 | reltime: DateConv( dt.toGMTString().replace( 'GMT', '+0000' ), 2 )
97 | };
98 | }
99 | }
100 | }
101 |
102 | cont.find( '.api_remaining_list' ).html( OutputTPL( 'api_remaining_list', { items: items } ) );
103 |
104 | for ( var i = 0, item, n = 0, _len = items.length ; i < _len ; i++ )
105 | {
106 | if ( items[i] == undefined )
107 | {
108 | continue;
109 | }
110 |
111 | item = cont.find( '.api_remaining_list' ).find( '.item:eq(' + n + ')' );
112 | n++;
113 |
114 | item.find( '.used' ).css( {
115 | width: 100 - items[i].per + '%',
116 | left: items[i].per + '%',
117 | } );
118 | }
119 |
120 | cont.trigger( 'contents_resize' ).activity( false );
121 | }
122 | else
123 | {
124 | ApiError( i18nGetMessage( 'i18n_0298' ), res );
125 | cont.activity( false );
126 | }
127 | }
128 | );
129 | };
130 |
131 | ////////////////////////////////////////////////////////////
132 | // 開始処理
133 | ////////////////////////////////////////////////////////////
134 | this.start = function() {
135 | ////////////////////////////////////////
136 | // 最小化/設定切替時のスクロール位置
137 | // 保存/復元
138 | ////////////////////////////////////////
139 | cont.on( 'contents_scrollsave', function( e, type ) {
140 | // 保存
141 | if ( type == 0 )
142 | {
143 | if ( scrollPos == null )
144 | {
145 | scrollPos = cont.find( '.api_remaining_list' ).scrollTop();
146 | }
147 | }
148 | // 復元
149 | else
150 | {
151 | if ( scrollPos != null )
152 | {
153 | cont.find( '.api_remaining_list' ).scrollTop( scrollPos );
154 | scrollPos = null;
155 | }
156 | }
157 | } );
158 |
159 | ////////////////////////////////////////
160 | // リサイズ処理
161 | ////////////////////////////////////////
162 | cont.on( 'contents_resize', function() {
163 | cont.find( '.api_remaining_list' ).height( cont.height() - cont.find( '.panel_btns' ).height() - 1 );
164 | } );
165 |
166 | ////////////////////////////////////////
167 | // このパネルを開いたアカウントが
168 | // 削除された場合
169 | ////////////////////////////////////////
170 | var AccountAliveCheck = function() {
171 | if ( g_cmn.account[cp.param['account_id']] == undefined )
172 | {
173 | // パネルを閉じる
174 | p.find( '.close' ).trigger( 'click', [false] );
175 | return false;
176 | }
177 |
178 | return true;
179 | };
180 |
181 | ////////////////////////////////////////
182 | // アカウント変更
183 | ////////////////////////////////////////
184 | cont.on( 'account_change', function( e, account_id ) {
185 | if ( cp.param['account_id'] == account_id )
186 | {
187 | }
188 | else
189 | {
190 | p.find( 'div.titlebar' ).find( '.titlename' ).text( g_cmn.account[account_id].screen_name );
191 | cp.param['account_id'] = account_id;
192 |
193 | cp.title = cp.title.replace( /(
).*(<\/span>)/,
194 | '$1' + g_cmn.account[account_id].screen_name + '$2' );
195 |
196 | // パネルリストの更新"
197 | $( document ).trigger( 'panellist_changed' );
198 |
199 | // 更新
200 | ListMake();
201 | }
202 | } );
203 |
204 | ////////////////////////////////////////
205 | // アカウント情報更新
206 | ////////////////////////////////////////
207 | cont.on( 'account_update', function() {
208 | AccountAliveCheck();
209 |
210 | // アカウント選択リスト更新
211 | var s = '';
212 | var id;
213 |
214 | for ( var i = 0, _len = g_cmn.account_order.length ; i < _len ; i++ )
215 | {
216 | id = g_cmn.account_order[i];
217 | s += '' + g_cmn.account[id].screen_name + '';
218 | }
219 |
220 | p.find( 'div.titlebar' ).find( '.titlename_list' ).html( s )
221 | .find( 'span' ).click( function( e ) {
222 | p.find( 'div.contents' ).trigger( 'account_change', [$( this ).attr( 'account_id' )] );
223 | $( this ).parent().hide();
224 | } );
225 | } );
226 |
227 | if ( !AccountAliveCheck() )
228 | {
229 | return;
230 | }
231 |
232 | ////////////////////////////////////////
233 | // API残数変更
234 | ////////////////////////////////////////
235 | cont.on( 'api_remaining_update', function( e, id ) {
236 | if ( id == cp.param['account_id'] )
237 | {
238 | ListMake();
239 | }
240 | } );
241 |
242 | // 全体を作成
243 | cont.addClass( 'api_remaining' )
244 | .html( OutputTPL( 'api_remaining', {} ) );
245 |
246 | cp.SetTitle( i18nGetMessage( 'i18n_0296' ) + ' (' + g_cmn.account[cp.param['account_id']].screen_name + ')', false );
247 |
248 | ////////////////////////////////////////
249 | // 更新ボタンクリック
250 | ////////////////////////////////////////
251 | cont.find( '.panel_btns' ).find( '.api_remaining_reload' ).click( function( e ) {
252 | // disabledなら処理しない
253 | if ( $( this ).hasClass( 'disabled' ) )
254 | {
255 | return;
256 | }
257 |
258 | ListMake();
259 |
260 | e.stopPropagation();
261 | } );
262 |
263 | // リスト部作成処理
264 | ListMake();
265 | };
266 |
267 | ////////////////////////////////////////////////////////////
268 | // 終了処理
269 | ////////////////////////////////////////////////////////////
270 | this.stop = function() {
271 | };
272 | }
273 |
--------------------------------------------------------------------------------
/js/contents/image.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | ////////////////////////////////////////////////////////////////////////////////
4 | // イメージ表示
5 | ////////////////////////////////////////////////////////////////////////////////
6 | Contents.image = function( cp )
7 | {
8 | var p = $( '#' + cp.id );
9 | var cont = p.find( 'div.contents' );
10 | var scaleX = 1, scaleY = 1, rotate = 0;
11 | var fit = true;
12 |
13 | cp.SetIcon( 'icon-image' );
14 |
15 | ////////////////////////////////////////////////////////////
16 | // タイトル設定
17 | ////////////////////////////////////////////////////////////
18 | const setTitle = ( append ) => {
19 | let title_url = ( cp.param['video'] && Array.isArray( cp.param['url'] ) ) ? cp.param['url'][0] : cp.param['url']
20 | title_url = title_url.replace( /api_key=\w+\&/, '' )
21 |
22 | if ( title_url.match( /^data:image\// ) )
23 | {
24 | title_url = i18nGetMessage( 'i18n_0256' )
25 | }
26 |
27 | cp.SetTitle( i18nGetMessage( 'i18n_0199' ) + ' - ' + title_url + append, false )
28 | }
29 |
30 | ////////////////////////////////////////////////////////////
31 | // 開始処理
32 | ////////////////////////////////////////////////////////////
33 | this.start = function() {
34 | setTitle()
35 | setTimeout( function() { cont.activity( { color: '#ffffff' } ); }, 0 );
36 |
37 | if ( cp.param['video'] )
38 | {
39 | let items = []
40 |
41 | if ( Array.isArray( cp.param['url'] ) ) {
42 | for ( let i = 0 ; i < cp.param['url'].length ; i++ ) {
43 | items.push( {
44 | url: cp.param['url'][i],
45 | contenttype: cp.param['contenttype'][i]
46 | } )
47 | }
48 | } else {
49 | items.push( {
50 | url: cp.param['url'],
51 | contenttype: cp.param['contenttype']
52 | } )
53 | }
54 |
55 | cont.addClass( 'image' )
56 | .html( OutputTPL( 'image', { items: items, video: true, poster: cp.param['poster'] } ) );
57 | }
58 | else
59 | {
60 | cont.addClass( 'image' )
61 | .html( OutputTPL( 'image', { url: cp.param['url'] } ) );
62 | }
63 |
64 | cont.find( '.resizebtn' ).hide();
65 |
66 | ////////////////////////////////////////
67 | // 画像のサイズをパネルに合わせる
68 | ////////////////////////////////////////
69 | var FitPanelSize = function() {
70 | var pw = cont.outerWidth();
71 | var ph = cont.outerHeight() - p.find( 'div.titlebar' ).outerHeight()+5;
72 |
73 | var nw, nh;
74 |
75 | if ( cp.param['video'] )
76 | {
77 | if ( cont.find( 'video' ).length ) {
78 | nw = cont.find( 'video' ).get( 0 ).videoWidth;
79 | nh = cont.find( 'video' ).get( 0 ).videoHeight;
80 | }
81 | }
82 | else
83 | {
84 | nw = cont.find( 'img.image' ).get( 0 ).naturalWidth;
85 | nh = cont.find( 'img.image' ).get( 0 ).naturalHeight;
86 | }
87 |
88 | var pnw = pw;
89 | var pnh = pw / nw * nh;
90 |
91 | if ( pnh > ph )
92 | {
93 | pnh = ph;
94 | pnw = ph / nh * nw;
95 | }
96 |
97 | cont.find( 'img.image, video' ).css( {
98 | width: pnw,
99 | height: pnh,
100 | } );
101 | };
102 |
103 | ////////////////////////////////////////
104 | // 画像のサイズを実サイズにする
105 | ////////////////////////////////////////
106 | var RealSize = function() {
107 | if ( cp.param['video'] )
108 | {
109 | var img = cont.find( 'video' );
110 |
111 | img.width( img.get( 0 ).videoWidth )
112 | .height( img.get( 0 ).videoHeight );
113 | }
114 | else
115 | {
116 | var img = cont.find( 'img.image' );
117 |
118 | img.width( img.get( 0 ).naturalWidth )
119 | .height( img.get( 0 ).naturalHeight );
120 | }
121 | };
122 |
123 | ////////////////////////////////////////
124 | // ロード完了
125 | ////////////////////////////////////////
126 | var LoadedEvent = function() {
127 | // 実サイズ
128 | var nw, nh;
129 |
130 | if ( cp.param['video'] )
131 | {
132 | nw = $( this ).get( 0 ).videoWidth;
133 | nh = $( this ).get( 0 ).videoHeight;
134 | setTitle( ' (' + nw + '×' + nh + ')')
135 | }
136 | else
137 | {
138 | nw = $( this ).get( 0 ).naturalWidth;
139 | nh = $( this ).get( 0 ).naturalHeight;
140 | setTitle( ' (' + nw + '×' + nh + ')' )
141 | }
142 |
143 | setTimeout( function() {cont.activity( false ); }, 0 );
144 |
145 | // 巨大画像の表示抑止
146 | var mainw = $( window ).width() * 0.95;
147 | var mainh = ( $( window ).height() ) * 0.85;
148 |
149 | if ( nw > mainw )
150 | {
151 | nh = mainw * nh / nw;
152 | nw = mainw;
153 | }
154 |
155 | if ( nh > mainh )
156 | {
157 | nw = mainh * nw / nh;
158 | nh = mainh;
159 | }
160 |
161 | // タイトルバーのボタン表示分の幅を確保
162 | var barsize = p.find( 'div.titlebar' ).find( '.close' ).outerWidth() * 3 + 48;
163 |
164 | nw = ( nw < barsize ) ? barsize : nw;
165 |
166 | if ( nh < 200 )
167 | {
168 | nh = 200;
169 | }
170 |
171 | nh = nh + p.find( 'div.titlebar' ).outerHeight() + 24;
172 |
173 | p.css( { width: nw, height: nh, left: ( $( 'body' ).outerWidth() - nw ) / 2 + $( document ).scrollLeft() } )
174 | .trigger( 'resize' );
175 |
176 | // 画像ダブルクリックで閉じる
177 | cont.find( 'img.image,video' ).on( 'dblclick', function( e ) {
178 | p.find( '.close' ).trigger( 'click', [false] );
179 | } );
180 |
181 | ////////////////////////////////////////
182 | // パネルサイズに合わせる
183 | ////////////////////////////////////////
184 | cont.find( '.img_panelsize' ).click( function( e ) {
185 | fit = true;
186 |
187 | FitPanelSize();
188 |
189 | p.trigger( 'resize' );
190 | e.stopPropagation();
191 | } );
192 |
193 | ////////////////////////////////////////
194 | // 実サイズで表示
195 | ////////////////////////////////////////
196 | cont.find( '.img_fullsize' ).click( function( e ) {
197 | fit = false;
198 |
199 | RealSize();
200 |
201 | p.trigger( 'resize' );
202 | e.stopPropagation();
203 | } );
204 |
205 | ////////////////////////////////////////
206 | // 上下反転
207 | ////////////////////////////////////////
208 | cont.find( '.img_udreverse' ).click( function( e ) {
209 | scaleY = ( scaleY == 1 ) ? -1 : 1;
210 |
211 | cont.find( 'img.image, video' ).css( { '-webkit-transform': 'scale(' + scaleX + ',' + scaleY + ') rotate(' + rotate + 'deg)' } );
212 | e.stopPropagation();
213 | } );
214 |
215 | ////////////////////////////////////////
216 | // 左右反転
217 | ////////////////////////////////////////
218 | cont.find( '.img_lrreverse' ).click( function( e ) {
219 | scaleX = ( scaleX == 1 ) ? -1 : 1;
220 |
221 | cont.find( 'img.image, video' ).css( { '-webkit-transform': 'scale(' + scaleX + ',' + scaleY + ') rotate(' + rotate + 'deg)' } );
222 | e.stopPropagation();
223 | } );
224 |
225 | ////////////////////////////////////////
226 | // 回転
227 | ////////////////////////////////////////
228 | cont.find( '.img_rotate' ).click( function( e ) {
229 | rotate = ( rotate == 270 ) ? 0 : rotate + 90;
230 |
231 | cont.find( 'img.image, video' ).css( { '-webkit-transform': 'scale(' + scaleX + ',' + scaleY + ') rotate(' + rotate + 'deg)' } );
232 | e.stopPropagation();
233 | } );
234 |
235 | ////////////////////////////////////////
236 | // リサイズボタン群表示
237 | ////////////////////////////////////////
238 | if ( !cp.param['video'] )
239 | {
240 | cont.mouseenter( function( e ) {
241 | cont.find( '.resizebtn' ).show();
242 | } );
243 | }
244 |
245 | ////////////////////////////////////////
246 | // リサイズボタン群非表示
247 | ////////////////////////////////////////
248 | cont.mouseleave( function( e ) {
249 | cont.find( '.resizebtn' ).hide();
250 | } );
251 |
252 | ////////////////////////////////////////
253 | // 音量
254 | ////////////////////////////////////////
255 | if ( cp.param['video'] ) {
256 | cont.find( 'video' )
257 | .prop( 'volume', g_cmn.video_volume )
258 | .on( 'volumechange', function() {
259 | g_cmn.video_volume = this.volume
260 | } )
261 | }
262 |
263 | // 初期表示
264 | cont.find( '.img_panelsize' ).trigger( 'click' );
265 | };
266 |
267 | cont.find( 'img.image' ).on( 'load', LoadedEvent );
268 | cont.find( 'video' ).on( 'loadedmetadata', LoadedEvent );
269 |
270 | if ( g_devmode ) {
271 | console.log( '--event-----------' )
272 | cont.find( 'video' ).on( 'loadstart', () => { console.log('loadstart') } )
273 | cont.find( 'video' ).on( 'suspend', () => { console.log('suspend') } )
274 | cont.find( 'video' ).on( 'abort', () => { console.log('abort') } )
275 | cont.find( 'video' ).on( 'error', () => { console.log('error') } )
276 | cont.find( 'video' ).on( 'emptied', () => { console.log('emptied') } )
277 | cont.find( 'video' ).on( 'stalled', () => { console.log('stalled') } )
278 | cont.find( 'video' ).on( 'loadedmetadata', () => { console.log('loadedmetadata') } )
279 | cont.find( 'video' ).on( 'canplay', () => { console.log('canplay') } )
280 | cont.find( 'video' ).on( 'playing', () => { console.log('playing') } )
281 | }
282 |
283 | ////////////////////////////////////////
284 | // 読み込み失敗
285 | ////////////////////////////////////////
286 | var ErrorEvent = function( e ) {
287 | if ( g_devmode ) {
288 | console.log( '読み込み失敗' )
289 | console.log( cont.find( 'video' ).get(0).error )
290 | }
291 |
292 | setTitle( ' (' + i18nGetMessage( 'i18n_0258' ) + ')' )
293 | setTimeout( function() { cont.activity( false ); }, 0 );
294 |
295 | cont.find( 'video' ).addClass( 'error' )
296 | //cont.find( 'video' ).remove()
297 | };
298 |
299 | cont.find( 'img.image,video' ).on( 'error', ErrorEvent );
300 |
301 | ////////////////////////////////////////
302 | // リサイズ処理
303 | ////////////////////////////////////////
304 | cont.on( 'contents_resize', function() {
305 | if ( fit )
306 | {
307 | FitPanelSize();
308 | }
309 | } );
310 | };
311 |
312 | ////////////////////////////////////////////////////////////
313 | // 終了処理
314 | ////////////////////////////////////////////////////////////
315 | this.stop = function() {
316 | };
317 | }
318 |
--------------------------------------------------------------------------------
/js/contents/accountset.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | ////////////////////////////////////////////////////////////////////////////////
4 | // アカウント設定
5 | ////////////////////////////////////////////////////////////////////////////////
6 | Contents.accountset = function( cp )
7 | {
8 | var p = $( '#' + cp.id );
9 | var cont = p.find( 'div.contents' );
10 |
11 | cp.SetIcon( 'icon-user' );
12 |
13 | var SetTitle = function() {
14 | cp.SetTitle( i18nGetMessage( 'i18n_0047' ) + '(' + g_cmn.account[cp.param.account_id].screen_name + ')', false );
15 |
16 | }
17 |
18 | ////////////////////////////////////////////////////////////
19 | // 初期入力値設定
20 | ////////////////////////////////////////////////////////////
21 | var MakeInput = function() {
22 | cont.html( '' )
23 | .addClass( 'accountset' );
24 |
25 | cont.activity( { color: '#ffffff' } );
26 |
27 | var param = {
28 | type: 'GET',
29 | url: ApiUrl( '1.1' ) + 'users/show.json',
30 | data: {
31 | user_id: g_cmn.account[cp.param['account_id']].user_id,
32 | },
33 | };
34 |
35 | SendRequest(
36 | {
37 | action: 'oauth_send',
38 | acsToken: g_cmn.account[cp.param['account_id']]['accessToken'],
39 | acsSecret: g_cmn.account[cp.param['account_id']]['accessSecret'],
40 | param: param,
41 | id:cp.param['account_id']
42 | },
43 | function( res )
44 | {
45 | if ( res.status == 200 )
46 | {
47 | cont.html( OutputTPL( 'accountset', {
48 | icon: res.json.profile_image_url_https,
49 | name: escapeHTML( res.json.name ),
50 | url: escapeHTML( res.json.url ),
51 | location: escapeHTML( res.json.location ),
52 | desc: escapeHTML( res.json.description ),
53 | } ) );
54 |
55 | $( '#iconselectbtn' ).removeClass( 'disabled' );
56 | $( '#iconuploadbtn' ).addClass( 'disabled' );
57 | $( '#profupdatebtn' ).removeClass( 'disabled' );
58 | }
59 | else
60 | {
61 | ApiError( i18nGetMessage( 'i18n_0160' ), res );
62 |
63 | cont.html( OutputTPL( 'accountset', {
64 | icon: '',
65 | name: '',
66 | url: '',
67 | location: '',
68 | desc: '',
69 | } ) );
70 |
71 | $( '#iconselectbtn' ).addClass( 'disabled' );
72 | $( '#iconuploadbtn' ).addClass( 'disabled' );
73 | $( '#profupdatebtn' ).addClass( 'disabled' );
74 | }
75 |
76 | $( 'panel' ).find( 'div.contents' ).trigger( 'api_remaining_update', [cp.param['account_id']] );
77 |
78 | g_cmn.account[cp.param['account_id']].icon = res.json.profile_image_url_https;
79 | $( '#head' ).trigger( 'account_update' );
80 |
81 | $( '#profname' ).focus();
82 |
83 | SetFont( true );
84 | cont.activity( false );
85 |
86 | ////////////////////////////////////////
87 | // ファイル選択ボタンクリック処理
88 | ////////////////////////////////////////
89 | $( '#iconselectbtn' ).click( function( e ) {
90 | // disabledなら処理しない
91 | if ( $( this ).hasClass( 'disabled' ) )
92 | {
93 | return;
94 | }
95 |
96 | $( '#iconupload_input' ).click();
97 | e.stopPropagation();
98 | } );
99 |
100 | ////////////////////////////////////////
101 | // ファイル選択変更時の処理
102 | ////////////////////////////////////////
103 | $( '#iconupload_input' ).change( function( e ) {
104 | if ( $( '#iconupload_input' )[0].files.length == 1 )
105 | {
106 | $( '#iconuploadbtn' ).removeClass( 'disabled' );
107 |
108 | var f = $( '#iconupload_input' )[0].files[0];
109 |
110 | $( '#iconuploadbox_select > span' ).html( f.name );
111 |
112 | if ( f.type.match( 'image.*' ) )
113 | {
114 | var reader = new FileReader();
115 |
116 | reader.onload = function( e ) {
117 | var result = e.target.result;
118 |
119 | $( '#iconimg' ).attr( 'src', result );
120 | };
121 |
122 | reader.readAsDataURL( f );
123 | }
124 | }
125 | else
126 | {
127 | $( '#iconuploadbtn' ).addClass( 'disabled' );
128 | $( '#iconuploadbox_select > span' ).html( i18nGetMessage( 'i18n_0119' ) + '
' + i18nGetMessage( 'i18n_0019' ) + '' );
129 | }
130 |
131 | e.stopPropagation();
132 | } );
133 |
134 | ////////////////////////////////////////
135 | // アイコン更新ボタンクリック処理
136 | ////////////////////////////////////////
137 | $( '#iconuploadbtn' ).click( function( e ) {
138 | // disabledなら処理しない
139 | if ( $( this ).hasClass( 'disabled' ) )
140 | {
141 | return;
142 | }
143 |
144 | // バックグラウンドの変数にアップロードするファイルを設定
145 | uploadIconFile = $( '#iconupload_input' ).get( 0 ).files[0];
146 |
147 | $( '#iconselectbtn' ).addClass( 'disabled' );
148 | $( '#iconuploadbtn' ).addClass( 'disabled' );
149 |
150 | Blackout( true );
151 | $( '#blackout' ).activity( { color: '#808080', width: 8, length: 14 } );
152 |
153 | SendRequest(
154 | {
155 | action: 'icon_upload',
156 | acsToken: g_cmn.account[cp.param['account_id']]['accessToken'],
157 | acsSecret: g_cmn.account[cp.param['account_id']]['accessSecret'],
158 | id: cp.param['account_id'],
159 | },
160 | function( res )
161 | {
162 | if ( res != '' )
163 | {
164 | $( '#iconimg' ).parent().activity( { color: 'ffffff' } );
165 |
166 | var before_url = $( '#iconimg' ).attr( 'src' );
167 | var chkcnt = 0;
168 |
169 | // アイコンの変更反映チェック
170 | var IconUpdateCheck = function() {
171 | var param = {
172 | type: 'GET',
173 | url: ApiUrl( '1.1' ) + 'users/show.json',
174 | data: {
175 | user_id: g_cmn.account[cp.param['account_id']].user_id,
176 | },
177 | };
178 |
179 | SendRequest(
180 | {
181 | action: 'oauth_send',
182 | acsToken: g_cmn.account[cp.param['account_id']]['accessToken'],
183 | acsSecret: g_cmn.account[cp.param['account_id']]['accessSecret'],
184 | param: param,
185 | id:cp.param['account_id']
186 | },
187 | function( res )
188 | {
189 | if ( res.status == 200 )
190 | {
191 | if ( res.json.profile_image_url_https != before_url )
192 | {
193 | $( '#iconimg' ).attr( 'src', res.json.profile_image_url_https )
194 | .parent().activity( false );
195 |
196 | g_cmn.account[cp.param['account_id']].icon = res.json.profile_image_url_https;
197 | $( '#head' ).trigger( 'account_update' );
198 |
199 | for ( var i = 0, _len = g_cmn.toolbar_user.length ; i < _len ; i++ )
200 | {
201 | if ( g_cmn.toolbar_user[i].user_id == g_cmn.account[cp.param['account_id']].user_id )
202 | {
203 | g_cmn.toolbar_user[i].icon = res.json.profile_image_url_https;
204 | }
205 | }
206 |
207 | UpdateToolbarUser();
208 | }
209 | else
210 | {
211 | chkcnt++;
212 |
213 | if ( chkcnt != 3 )
214 | {
215 | setTimeout( IconUpdateCheck, 3000 );
216 | }
217 | else
218 | {
219 | $( '#iconimg' ).parent().activity( false );
220 | }
221 | }
222 | }
223 | else
224 | {
225 | $( '#iconimg' ).parent().activity( false );
226 | }
227 |
228 | $( 'panel' ).find( 'div.contents' ).trigger( 'api_remaining_update', [cp.param['account_id']] );
229 | }
230 | );
231 | };
232 |
233 | setTimeout( IconUpdateCheck, 5000 );
234 | }
235 | else
236 | {
237 | MessageBox( i18nGetMessage( 'i18n_0118' ) );
238 | }
239 |
240 | Blackout( false );
241 | $( '#blackout' ).activity( false );
242 |
243 | $( '#iconselectbtn' ).removeClass( 'disabled' );
244 | $( '#iconuploadbtn' ).removeClass( 'disabled' );
245 | }
246 | );
247 |
248 | e.stopPropagation();
249 | } );
250 |
251 | ////////////////////////////////////////
252 | // プロフィール保存ボタンクリック処理
253 | ////////////////////////////////////////
254 | $( '#profupdatebtn' ).click( function( e ) {
255 | // disabledなら処理しない
256 | if ( $( this ).hasClass( 'disabled' ) )
257 | {
258 | return;
259 | }
260 |
261 | var param = {
262 | type: 'POST',
263 | url: ApiUrl( '1.1' ) + 'account/update_profile.json',
264 | data: {
265 | name: $( '#profname' ).val(),
266 | url: $( '#profurl' ).val(),
267 | location: $( '#proflocation' ).val(),
268 | description: $( '#profdesc' ).val()
269 | }
270 | };
271 |
272 | Blackout( true );
273 | $( '#blackout' ).activity( { color: '#808080', width: 8, length: 14 } );
274 |
275 | SendRequest(
276 | {
277 | action: 'oauth_send',
278 | acsToken: g_cmn.account[cp.param['account_id']]['accessToken'],
279 | acsSecret: g_cmn.account[cp.param['account_id']]['accessSecret'],
280 | param: param,
281 | id: cp.param['account_id']
282 | },
283 | function( res )
284 | {
285 | if ( res.status == 200 )
286 | {
287 | }
288 | else
289 | {
290 | console.log( 'status[' + res.status + ']' );
291 |
292 | $( this ).removeClass( 'disabled' );
293 |
294 | ApiError( i18nGetMessage( 'i18n_0147' ), res );
295 | }
296 |
297 | Blackout( false );
298 | $( '#blackout' ).activity( false );
299 | }
300 | );
301 | } );
302 | }
303 | );
304 | };
305 |
306 | ////////////////////////////////////////////////////////////
307 | // 開始処理
308 | ////////////////////////////////////////////////////////////
309 | this.start = function() {
310 | ////////////////////////////////////////
311 | // このパネルを開いたアカウントが
312 | // 削除された場合
313 | ////////////////////////////////////////
314 | var AccountAliveCheck = function() {
315 | if ( g_cmn.account[cp.param['account_id']] == undefined )
316 | {
317 | // パネルを閉じる
318 | p.find( '.close' ).trigger( 'click', [false] );
319 | return false;
320 | }
321 |
322 | return true;
323 | };
324 |
325 | ////////////////////////////////////////
326 | // アカウント情報更新
327 | ////////////////////////////////////////
328 | cont.on( 'account_update', function() {
329 | AccountAliveCheck();
330 | } );
331 |
332 | ////////////////////////////////////////
333 | // アカウント変更
334 | ////////////////////////////////////////
335 | cont.on( 'account_change', function() {
336 | SetTitle();
337 | MakeInput();
338 | } );
339 |
340 | SetTitle();
341 |
342 | // 全体を作成
343 | MakeInput();
344 | };
345 |
346 | ////////////////////////////////////////////////////////////
347 | // 終了処理
348 | ////////////////////////////////////////////////////////////
349 | this.stop = function() {
350 | };
351 | }
352 |
--------------------------------------------------------------------------------
/js/contents/usersearch.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | ////////////////////////////////////////////////////////////////////////////////
4 | // ユーザ検索一覧
5 | ////////////////////////////////////////////////////////////////////////////////
6 | Contents.usersearch = function( cp )
7 | {
8 | var p = $( '#' + cp.id );
9 | var cont = p.find( 'div.contents' );
10 | var page = 1;
11 | var usersearch_list;
12 | var scrollPos = null;
13 | var users = {};
14 |
15 | cp.SetIcon( 'icon-search' );
16 |
17 | ////////////////////////////////////////////////////////////
18 | // リスト部作成
19 | ////////////////////////////////////////////////////////////
20 | var ListMake = function( type ) {
21 | var param = {
22 | type: 'GET',
23 | url: ApiUrl( '1.1' ) + 'users/search.json',
24 | data: {
25 | q: cp.param['q'],
26 | count: 20,
27 | page: page,
28 | },
29 | };
30 |
31 | if ( type == 'init' || type == 'reload' )
32 | {
33 | param.data.page = 1;
34 | }
35 |
36 | cont.activity( { color: '#ffffff' } );
37 |
38 | SendRequest(
39 | {
40 | action: 'oauth_send',
41 | acsToken: g_cmn.account[cp.param['account_id']]['accessToken'],
42 | acsSecret: g_cmn.account[cp.param['account_id']]['accessSecret'],
43 | param: param,
44 | id: cp.param['account_id']
45 | },
46 | function( res )
47 | {
48 | if ( res.status == 200 )
49 | {
50 | var s = '';
51 | var json = res.json;
52 | var items = new Array();
53 | var len = 0;
54 | var created_at = '';
55 |
56 | for ( var i = 0, _len = json.length ; i < _len ; i++ )
57 | {
58 | if ( users[json[i].id_str] )
59 | {
60 | continue;
61 | }
62 | else
63 | {
64 | len++;
65 | users[json[i].id_str] = true;
66 | }
67 |
68 | // 日付にはとりあえずアカウントの作成日を設定
69 | created_at = json[i].created_at;
70 |
71 | // 最新ツイートが設定されている場合は、そのツイートの日時を設定
72 | if ( json[i].status != undefined )
73 | {
74 | if ( json[i].status.created_at != undefined )
75 | {
76 | created_at = json[i].status.created_at;
77 | }
78 | }
79 |
80 | var isfriend = IsFriend( cp.param['account_id'], json[i].id_str );
81 | var isfollower = IsFollower( cp.param['account_id'], json[i].id_str );
82 |
83 | const dt = new Date()
84 | const cr = DateConv( created_at, 0 )
85 | const compdate = CompareDate( dt.getFullYear(), dt.getMonth() + 1, dt.getDate(),
86 | cr.substring( 0, 4 ), cr.substring( 5, 7 ), cr.substring( 8, 10 ) );
87 |
88 | items.push( {
89 | icon: json[i].profile_image_url_https,
90 | screen_name: json[i].screen_name,
91 | name: twemoji.parse( json[i].name ),
92 | follow: NumFormat( json[i].friends_count ),
93 | follower: NumFormat( json[i].followers_count ),
94 | count: NumFormat( json[i].statuses_count ),
95 | description: json[i].description,
96 | verified: json[i].verified,
97 | protected: json[i].protected,
98 | user_id: json[i].id_str,
99 | created_at: created_at,
100 | ismutual: isfriend & isfollower,
101 | isfriend: isfriend & !isfollower,
102 | isfollower: !isfriend & isfollower,
103 | latest_date: ( json[i].status && json[i].status.created_at ) ? DateConv( json[i].status.created_at, 0 ) : null,
104 | sleeping: ( compdate > 30 )
105 | } );
106 | }
107 |
108 | s = OutputTPL( 'user_list', { items: items } );
109 |
110 | // もっと読む
111 | var AppendReadmore = function() {
112 | if ( len > 0 )
113 | {
114 | usersearch_list.append(
115 | '' );
116 | }
117 | };
118 |
119 | switch ( type )
120 | {
121 | // 初期、更新
122 | case 'init':
123 | case 'reload':
124 | usersearch_list.html( s );
125 | usersearch_list.scrollTop( 0 );
126 |
127 | page++;
128 | AppendReadmore();
129 | break;
130 | // もっと読む
131 | case 'old':
132 | if ( len > 0 )
133 | {
134 | usersearch_list.append( s );
135 |
136 | page++;
137 | AppendReadmore();
138 | }
139 |
140 | usersearch_list.find( '.readmore' ).first().remove();
141 | $( '#tooltip' ).hide();
142 |
143 | break;
144 | }
145 |
146 | cont.trigger( 'contents_resize' );
147 | }
148 | else
149 | {
150 | // もっと読むで404が返ってきた場合
151 | if ( type == 'old' && res.status == 404 )
152 | {
153 | usersearch_list.find( '.readmore' ).first().remove();
154 | $( '#tooltip' ).hide();
155 | }
156 | else
157 | {
158 | ApiError( i18nGetMessage( 'i18n_0213' ), res );
159 |
160 | if ( type == 'old' )
161 | {
162 | usersearch_list.find( '.readmore' ).removeClass( 'disabled' );
163 | }
164 | }
165 | }
166 |
167 | cont.activity( false );
168 |
169 | $( 'panel' ).find( 'div.contents' ).trigger( 'api_remaining_update', [cp.param['account_id']] );
170 | }
171 | );
172 | };
173 |
174 | ////////////////////////////////////////////////////////////
175 | // 開始処理
176 | ////////////////////////////////////////////////////////////
177 | this.start = function() {
178 | ////////////////////////////////////////
179 | // 最小化/設定切替時のスクロール位置
180 | // 保存/復元
181 | ////////////////////////////////////////
182 | cont.on( 'contents_scrollsave', function( e, type ) {
183 | // 保存
184 | if ( type == 0 )
185 | {
186 | if ( scrollPos == null )
187 | {
188 | scrollPos = usersearch_list.scrollTop();
189 | }
190 | }
191 | // 復元
192 | else
193 | {
194 | if ( scrollPos != null )
195 | {
196 | usersearch_list.scrollTop( scrollPos );
197 | scrollPos = null;
198 | }
199 | }
200 | } );
201 |
202 | ////////////////////////////////////////
203 | // リサイズ処理
204 | ////////////////////////////////////////
205 | cont.on( 'contents_resize', function() {
206 | cont.find( '.usersearch_list' ).height( cont.height() - cont.find( '.panel_btns' ).height() - 1 );
207 | } );
208 |
209 | ////////////////////////////////////////
210 | // アカウント変更
211 | ////////////////////////////////////////
212 | cont.on( 'account_change', function( e, account_id ) {
213 | if ( cp.param['account_id'] == account_id )
214 | {
215 | }
216 | else
217 | {
218 | p.find( 'div.titlebar' ).find( '.titlename' ).text( g_cmn.account[account_id].screen_name );
219 | cp.param['account_id'] = account_id;
220 |
221 | cp.title = cp.title.replace( /().*(<\/span>)/,
222 | '$1' + g_cmn.account[account_id].screen_name + '$2' );
223 |
224 | // パネルリストの更新"
225 | $( document ).trigger( 'panellist_changed' );
226 |
227 | // 更新
228 | cont.find( '.panel_btns' ).find( '.usersearch_reload' ).trigger( 'click' );
229 | }
230 | } );
231 |
232 | ////////////////////////////////////////
233 | // このパネルを開いたアカウントが
234 | // 削除された場合
235 | ////////////////////////////////////////
236 | var AccountAliveCheck = function() {
237 | if ( g_cmn.account[cp.param['account_id']] == undefined )
238 | {
239 | // パネルを閉じる
240 | p.find( '.close' ).trigger( 'click', [false] );
241 | return false;
242 | }
243 |
244 | return true;
245 | };
246 |
247 | ////////////////////////////////////////
248 | // アカウント情報更新
249 | ////////////////////////////////////////
250 | cont.on( 'account_update', function() {
251 | AccountAliveCheck();
252 |
253 | // アカウント選択リスト更新
254 | var s = '';
255 | var id;
256 |
257 | for ( var i = 0, _len = g_cmn.account_order.length ; i < _len ; i++ )
258 | {
259 | id = g_cmn.account_order[i];
260 | s += '' + g_cmn.account[id].screen_name + '';
261 | }
262 |
263 | p.find( 'div.titlebar' ).find( '.titlename_list' ).html( s )
264 | .find( 'span' ).click( function( e ) {
265 | p.find( 'div.contents' ).trigger( 'account_change', [$( this ).attr( 'account_id' )] );
266 | $( this ).parent().hide();
267 | } );
268 | } );
269 |
270 | if ( !AccountAliveCheck() )
271 | {
272 | return;
273 | }
274 |
275 | // 全体を作成
276 | cont.addClass( 'usersearch' )
277 | .html( OutputTPL( 'usersearch', {} ) );
278 |
279 | usersearch_list = cont.find( '.usersearch_list' );
280 |
281 | cp.SetTitle( i18nGetMessage( 'i18n_0105', [cp.param['q']] ) + ' (' + g_cmn.account[cp.param['account_id']]['screen_name'] + ')', false );
282 |
283 | ////////////////////////////////////////
284 | // 更新ボタンクリック
285 | ////////////////////////////////////////
286 | cont.find( '.panel_btns' ).find( '.usersearch_reload' ).click( function( e ) {
287 | // disabledなら処理しない
288 | if ( $( this ).hasClass( 'disabled' ) )
289 | {
290 | return;
291 | }
292 |
293 | ListMake( 'reload' );
294 | } );
295 |
296 | ////////////////////////////////////////
297 | // ユーザ名クリック
298 | ////////////////////////////////////////
299 | usersearch_list.on( 'click', '> div.item .screen_name', function( e ) {
300 | OpenUserTimeline( $( this ).text(), cp.param['account_id'] );
301 | e.stopPropagation();
302 | } );
303 |
304 | ////////////////////////////////////////
305 | // アイコンクリック処理
306 | ////////////////////////////////////////
307 | usersearch_list.on( 'click', '> div.item .icon img', function( e ) {
308 | OpenUserShow( $( this ).parent().parent().attr( 'screen_name' ),
309 | $( this ).parent().parent().attr( 'user_id' ),
310 | cp.param['account_id'] );
311 |
312 | e.stopPropagation();
313 | } );
314 |
315 | ////////////////////////////////////////
316 | // もっと読むクリック処理
317 | ////////////////////////////////////////
318 | usersearch_list.on( 'click', '> div.readmore', function( e ) {
319 | // disabledなら処理しない
320 | if ( $( this ).hasClass( 'disabled' ) )
321 | {
322 | return;
323 | }
324 |
325 | $( this ).addClass( 'disabled' );
326 |
327 | ListMake( 'old' );
328 |
329 | e.stopPropagation();
330 | } );
331 |
332 | ////////////////////////////////////////
333 | // アイコンにカーソルを乗せたとき
334 | ////////////////////////////////////////
335 | usersearch_list.on( 'mouseenter mouseleave', '> div.item div.icon > img', function( e ) {
336 | if ( e.type == 'mouseenter' )
337 | {
338 | // Draggableの設定をする
339 | SetDraggable( $( this ), p, cp );
340 | }
341 | else
342 | {
343 | $( '#tooltip' ).hide();
344 | }
345 | } );
346 |
347 | ////////////////////////////////////////
348 | // 一番下までスクロールで
349 | // 「もっと読む」クリック
350 | ////////////////////////////////////////
351 | usersearch_list.scroll(
352 | function()
353 | {
354 | if ( g_cmn.cmn_param['autoreadmore'] == 1 )
355 | {
356 | if ( usersearch_list.prop( 'scrollHeight' ) == usersearch_list.scrollTop() + usersearch_list.innerHeight() )
357 | {
358 | usersearch_list.find( '.readmore' ).trigger( 'click' );
359 | }
360 | }
361 | }
362 | );
363 |
364 | // リスト部作成処理
365 | ListMake( 'init' );
366 | };
367 |
368 | ////////////////////////////////////////////////////////////
369 | // 終了処理
370 | ////////////////////////////////////////////////////////////
371 | this.stop = function() {
372 | };
373 | }
374 |
--------------------------------------------------------------------------------
/js/lib/twemoji.js:
--------------------------------------------------------------------------------
1 | /*! Copyright Twitter Inc. and other contributors. Licensed under MIT */
2 | var twemoji=function(){"use strict";var twemoji={base:"https://twemoji.maxcdn.com/v/13.0.2/",ext:".png",size:"72x72",className:"emoji",convert:{fromCodePoint:fromCodePoint,toCodePoint:toCodePoint},onerror:function onerror(){if(this.parentNode){this.parentNode.replaceChild(createText(this.alt,false),this)}},parse:parse,replace:replace,test:test},escaper={"&":"&","<":"<",">":">","'":"'",'"':"""},re=/(?:\ud83d\udc68\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc68\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc68\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\u200d\ud83e\udd1d\u200d\ud83e\uddd1|\ud83d\udc6b\ud83c[\udffb-\udfff]|\ud83d\udc6c\ud83c[\udffb-\udfff]|\ud83d\udc6d\ud83c[\udffb-\udfff]|\ud83d[\udc6b-\udc6d])|(?:\ud83d[\udc68\udc69]|\ud83e\uddd1)(?:\ud83c[\udffb-\udfff])?\u200d(?:\u2695\ufe0f|\u2696\ufe0f|\u2708\ufe0f|\ud83c[\udf3e\udf73\udf7c\udf84\udf93\udfa4\udfa8\udfeb\udfed]|\ud83d[\udcbb\udcbc\udd27\udd2c\ude80\ude92]|\ud83e[\uddaf-\uddb3\uddbc\uddbd])|(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75]|\u26f9)((?:\ud83c[\udffb-\udfff]|\ufe0f)\u200d[\u2640\u2642]\ufe0f)|(?:\ud83c[\udfc3\udfc4\udfca]|\ud83d[\udc6e\udc70\udc71\udc73\udc77\udc81\udc82\udc86\udc87\ude45-\ude47\ude4b\ude4d\ude4e\udea3\udeb4-\udeb6]|\ud83e[\udd26\udd35\udd37-\udd39\udd3d\udd3e\uddb8\uddb9\uddcd-\uddcf\uddd6-\udddd])(?:\ud83c[\udffb-\udfff])?\u200d[\u2640\u2642]\ufe0f|(?:\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d[\udc68\udc69]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68|\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d[\udc68\udc69]|\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f|\ud83c\udff3\ufe0f\u200d\ud83c\udf08|\ud83c\udff4\u200d\u2620\ufe0f|\ud83d\udc15\u200d\ud83e\uddba|\ud83d\udc3b\u200d\u2744\ufe0f|\ud83d\udc41\u200d\ud83d\udde8|\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc6f\u200d\u2640\ufe0f|\ud83d\udc6f\u200d\u2642\ufe0f|\ud83e\udd3c\u200d\u2640\ufe0f|\ud83e\udd3c\u200d\u2642\ufe0f|\ud83e\uddde\u200d\u2640\ufe0f|\ud83e\uddde\u200d\u2642\ufe0f|\ud83e\udddf\u200d\u2640\ufe0f|\ud83e\udddf\u200d\u2642\ufe0f|\ud83d\udc08\u200d\u2b1b)|[#*0-9]\ufe0f?\u20e3|(?:[©®\u2122\u265f]\ufe0f)|(?:\ud83c[\udc04\udd70\udd71\udd7e\udd7f\ude02\ude1a\ude2f\ude37\udf21\udf24-\udf2c\udf36\udf7d\udf96\udf97\udf99-\udf9b\udf9e\udf9f\udfcd\udfce\udfd4-\udfdf\udff3\udff5\udff7]|\ud83d[\udc3f\udc41\udcfd\udd49\udd4a\udd6f\udd70\udd73\udd76-\udd79\udd87\udd8a-\udd8d\udda5\udda8\uddb1\uddb2\uddbc\uddc2-\uddc4\uddd1-\uddd3\udddc-\uddde\udde1\udde3\udde8\uddef\uddf3\uddfa\udecb\udecd-\udecf\udee0-\udee5\udee9\udef0\udef3]|[\u203c\u2049\u2139\u2194-\u2199\u21a9\u21aa\u231a\u231b\u2328\u23cf\u23ed-\u23ef\u23f1\u23f2\u23f8-\u23fa\u24c2\u25aa\u25ab\u25b6\u25c0\u25fb-\u25fe\u2600-\u2604\u260e\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262a\u262e\u262f\u2638-\u263a\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267b\u267f\u2692-\u2697\u2699\u269b\u269c\u26a0\u26a1\u26a7\u26aa\u26ab\u26b0\u26b1\u26bd\u26be\u26c4\u26c5\u26c8\u26cf\u26d1\u26d3\u26d4\u26e9\u26ea\u26f0-\u26f5\u26f8\u26fa\u26fd\u2702\u2708\u2709\u270f\u2712\u2714\u2716\u271d\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u2764\u27a1\u2934\u2935\u2b05-\u2b07\u2b1b\u2b1c\u2b50\u2b55\u3030\u303d\u3297\u3299])(?:\ufe0f|(?!\ufe0e))|(?:(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75\udd90]|[\u261d\u26f7\u26f9\u270c\u270d])(?:\ufe0f|(?!\ufe0e))|(?:\ud83c[\udf85\udfc2-\udfc4\udfc7\udfca]|\ud83d[\udc42\udc43\udc46-\udc50\udc66-\udc69\udc6e\udc70-\udc78\udc7c\udc81-\udc83\udc85-\udc87\udcaa\udd7a\udd95\udd96\ude45-\ude47\ude4b-\ude4f\udea3\udeb4-\udeb6\udec0\udecc]|\ud83e[\udd0c\udd0f\udd18-\udd1c\udd1e\udd1f\udd26\udd30-\udd39\udd3d\udd3e\udd77\uddb5\uddb6\uddb8\uddb9\uddbb\uddcd-\uddcf\uddd1-\udddd]|[\u270a\u270b]))(?:\ud83c[\udffb-\udfff])?|(?:\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f|\ud83c\udde6\ud83c[\udde8-\uddec\uddee\uddf1\uddf2\uddf4\uddf6-\uddfa\uddfc\uddfd\uddff]|\ud83c\udde7\ud83c[\udde6\udde7\udde9-\uddef\uddf1-\uddf4\uddf6-\uddf9\uddfb\uddfc\uddfe\uddff]|\ud83c\udde8\ud83c[\udde6\udde8\udde9\uddeb-\uddee\uddf0-\uddf5\uddf7\uddfa-\uddff]|\ud83c\udde9\ud83c[\uddea\uddec\uddef\uddf0\uddf2\uddf4\uddff]|\ud83c\uddea\ud83c[\udde6\udde8\uddea\uddec\udded\uddf7-\uddfa]|\ud83c\uddeb\ud83c[\uddee-\uddf0\uddf2\uddf4\uddf7]|\ud83c\uddec\ud83c[\udde6\udde7\udde9-\uddee\uddf1-\uddf3\uddf5-\uddfa\uddfc\uddfe]|\ud83c\udded\ud83c[\uddf0\uddf2\uddf3\uddf7\uddf9\uddfa]|\ud83c\uddee\ud83c[\udde8-\uddea\uddf1-\uddf4\uddf6-\uddf9]|\ud83c\uddef\ud83c[\uddea\uddf2\uddf4\uddf5]|\ud83c\uddf0\ud83c[\uddea\uddec-\uddee\uddf2\uddf3\uddf5\uddf7\uddfc\uddfe\uddff]|\ud83c\uddf1\ud83c[\udde6-\udde8\uddee\uddf0\uddf7-\uddfb\uddfe]|\ud83c\uddf2\ud83c[\udde6\udde8-\udded\uddf0-\uddff]|\ud83c\uddf3\ud83c[\udde6\udde8\uddea-\uddec\uddee\uddf1\uddf4\uddf5\uddf7\uddfa\uddff]|\ud83c\uddf4\ud83c\uddf2|\ud83c\uddf5\ud83c[\udde6\uddea-\udded\uddf0-\uddf3\uddf7-\uddf9\uddfc\uddfe]|\ud83c\uddf6\ud83c\udde6|\ud83c\uddf7\ud83c[\uddea\uddf4\uddf8\uddfa\uddfc]|\ud83c\uddf8\ud83c[\udde6-\uddea\uddec-\uddf4\uddf7-\uddf9\uddfb\uddfd-\uddff]|\ud83c\uddf9\ud83c[\udde6\udde8\udde9\uddeb-\udded\uddef-\uddf4\uddf7\uddf9\uddfb\uddfc\uddff]|\ud83c\uddfa\ud83c[\udde6\uddec\uddf2\uddf3\uddf8\uddfe\uddff]|\ud83c\uddfb\ud83c[\udde6\udde8\uddea\uddec\uddee\uddf3\uddfa]|\ud83c\uddfc\ud83c[\uddeb\uddf8]|\ud83c\uddfd\ud83c\uddf0|\ud83c\uddfe\ud83c[\uddea\uddf9]|\ud83c\uddff\ud83c[\udde6\uddf2\uddfc]|\ud83c[\udccf\udd8e\udd91-\udd9a\udde6-\uddff\ude01\ude32-\ude36\ude38-\ude3a\ude50\ude51\udf00-\udf20\udf2d-\udf35\udf37-\udf7c\udf7e-\udf84\udf86-\udf93\udfa0-\udfc1\udfc5\udfc6\udfc8\udfc9\udfcf-\udfd3\udfe0-\udff0\udff4\udff8-\udfff]|\ud83d[\udc00-\udc3e\udc40\udc44\udc45\udc51-\udc65\udc6a\udc6f\udc79-\udc7b\udc7d-\udc80\udc84\udc88-\udca9\udcab-\udcfc\udcff-\udd3d\udd4b-\udd4e\udd50-\udd67\udda4\uddfb-\ude44\ude48-\ude4a\ude80-\udea2\udea4-\udeb3\udeb7-\udebf\udec1-\udec5\uded0-\uded2\uded5-\uded7\udeeb\udeec\udef4-\udefc\udfe0-\udfeb]|\ud83e[\udd0d\udd0e\udd10-\udd17\udd1d\udd20-\udd25\udd27-\udd2f\udd3a\udd3c\udd3f-\udd45\udd47-\udd76\udd78\udd7a-\uddb4\uddb7\uddba\uddbc-\uddcb\uddd0\uddde-\uddff\ude70-\ude74\ude78-\ude7a\ude80-\ude86\ude90-\udea8\udeb0-\udeb6\udec0-\udec2\uded0-\uded6]|[\u23e9-\u23ec\u23f0\u23f3\u267e\u26ce\u2705\u2728\u274c\u274e\u2753-\u2755\u2795-\u2797\u27b0\u27bf\ue50a])|\ufe0f/g,UFE0Fg=/\uFE0F/g,U200D=String.fromCharCode(8205),rescaper=/[&<>'"]/g,shouldntBeParsed=/^(?:iframe|noframes|noscript|script|select|style|textarea)$/,fromCharCode=String.fromCharCode;return twemoji;function createText(text,clean){return document.createTextNode(clean?text.replace(UFE0Fg,""):text)}function escapeHTML(s){return s.replace(rescaper,replacer)}function defaultImageSrcGenerator(icon,options){return"".concat(options.base,options.size,"/",icon,options.ext)}function grabAllTextNodes(node,allText){var childNodes=node.childNodes,length=childNodes.length,subnode,nodeType;while(length--){subnode=childNodes[length];nodeType=subnode.nodeType;if(nodeType===3){allText.push(subnode)}else if(nodeType===1&&!("ownerSVGElement"in subnode)&&!shouldntBeParsed.test(subnode.nodeName.toLowerCase())){grabAllTextNodes(subnode,allText)}}return allText}function grabTheRightIcon(rawText){return toCodePoint(rawText.indexOf(U200D)<0?rawText.replace(UFE0Fg,""):rawText)}function parseNode(node,options){var allText=grabAllTextNodes(node,[]),length=allText.length,attrib,attrname,modified,fragment,subnode,text,match,i,index,img,rawText,iconId,src;while(length--){modified=false;fragment=document.createDocumentFragment();subnode=allText[length];text=subnode.nodeValue;i=0;while(match=re.exec(text)){index=match.index;if(index!==i){fragment.appendChild(createText(text.slice(i,index),true))}rawText=match[0];iconId=grabTheRightIcon(rawText);i=index+rawText.length;src=options.callback(iconId,options);if(iconId&&src){img=new Image;img.onerror=options.onerror;img.setAttribute("draggable","false");attrib=options.attributes(rawText,iconId);for(attrname in attrib){if(attrib.hasOwnProperty(attrname)&&attrname.indexOf("on")!==0&&!img.hasAttribute(attrname)){img.setAttribute(attrname,attrib[attrname])}}img.className=options.className;img.alt=rawText;img.src=src;modified=true;fragment.appendChild(img)}if(!img)fragment.appendChild(createText(rawText,false));img=null}if(modified){if(i")}return ret})}function replacer(m){return escaper[m]}function returnNull(){return null}function toSizeSquaredAsset(value){return typeof value==="number"?value+"x"+value:value}function fromCodePoint(codepoint){var code=typeof codepoint==="string"?parseInt(codepoint,16):codepoint;if(code<65536){return fromCharCode(code)}code-=65536;return fromCharCode(55296+(code>>10),56320+(code&1023))}function parse(what,how){if(!how||typeof how==="function"){how={callback:how}}return(typeof what==="string"?parseString:parseNode)(what,{callback:how.callback||defaultImageSrcGenerator,attributes:typeof how.attributes==="function"?how.attributes:returnNull,base:typeof how.base==="string"?how.base:twemoji.base,ext:how.ext||twemoji.ext,size:how.folder||toSizeSquaredAsset(how.size||twemoji.size),className:how.className||twemoji.className,onerror:how.onerror||twemoji.onerror})}function replace(text,callback){return String(text).replace(re,callback)}function test(text){re.lastIndex=0;var result=re.test(text);re.lastIndex=0;return result}function toCodePoint(unicodeSurrogates,sep){var r=[],c=0,p=0,i=0;while(i 0 )
258 | {
259 | setting.find( '.feed_append' ).removeClass( 'disabled' );
260 | }
261 | else
262 | {
263 | setting.find( '.feed_append' ).addClass( 'disabled' );
264 | }
265 | } );
266 |
267 | ////////////////////////////////////////
268 | // 適用ボタンクリック処理
269 | ////////////////////////////////////////
270 | setting.find( '.rsssetting_apply' ).click( function( e ) {
271 | // disabedなら処理しない
272 | if ( $( this ).hasClass( 'disabled' ) )
273 | {
274 | return;
275 | }
276 |
277 | // タイトル
278 | var title = setting.find( '.set_title' ).val();
279 |
280 | if ( title.length <= 0 )
281 | {
282 | MessageBox( i18nGetMessage( 'i18n_0076' ) );
283 | setting.find( '.set_title' ).focus();
284 | return false;
285 | }
286 |
287 | cp.param['title'] = title;
288 | cp.SetTitle( title, true );
289 |
290 | // 新着読み込み
291 | cp.param['reload_time'] = setting.find( '.set_reload_time' ).slider( 'value' );
292 |
293 | var _cp = {
294 | param: {
295 | count: cp.param['count'],
296 | showdesc: cp.param['showdesc']
297 | }
298 | };
299 |
300 | // 取得エントリ数
301 | cp.param['count'] = setting.find( '.set_count' ).slider( 'value' );
302 |
303 | // 説明表示
304 | cp.param['showdesc'] = setting.find( '.set_showdesc' ).prop( 'checked' ) ? 1 : 0;
305 |
306 | if ( _cp.param['count'] != cp.param['count'] || _cp.param['showdesc'] != cp.param['showdesc'] )
307 | {
308 | feedchange = true;
309 | }
310 |
311 | rss_list.trigger( 'reload_timer' );
312 |
313 | setting.find( '.rsssetting_apply' ).addClass( 'disabled' );
314 |
315 | if ( feedchange )
316 | {
317 | feedchange = false;
318 | ListMake();
319 | p.find( 'div.titlebar' ).find( '.setting' ).trigger( 'click' );
320 | }
321 |
322 | // RSSパネル管理に登録
323 | var _id = cp.id.replace( /^panel_/, '' );
324 |
325 | g_cmn.rss_panel[_id] = {
326 | id: _id,
327 | param: cp.param,
328 | };
329 |
330 | // RSSパネル一覧を表示している場合は一覧更新
331 | var pid = IsUnique( 'rsslist' );
332 |
333 | if ( pid != null )
334 | {
335 | $( '#rsslist_reload' ).trigger( 'click' );
336 | SetFront( p );
337 | }
338 |
339 | SaveData();
340 |
341 | e.stopPropagation();
342 | } );
343 |
344 | ////////////////////////////////////////
345 | // 登録ボタンクリック処理
346 | ////////////////////////////////////////
347 | setting.find( '.feed_append' ).click( function( e ) {
348 | // disabedなら処理しない
349 | if ( $( this ).hasClass( 'disabled' ) )
350 | {
351 | return;
352 | }
353 |
354 | var url = setting.find( '.set_feed' ).val();
355 |
356 | // 登録済み?
357 | for ( var i = 0, _len = cp.param['urls'].length ; i < _len ; i++ )
358 | {
359 | if ( cp.param['urls'][i].url == url )
360 | {
361 | MessageBox( i18nGetMessage( 'i18n_0257' ) );
362 | setting.find( '.set_feed' ).focus();
363 | return;
364 | }
365 | }
366 |
367 | setting.find( '.rsssetting_items .kinditems' ).last().activity( { color: '#ffffff' } );
368 | setting.find( '.feed_append' ).addClass( 'disabled' );
369 |
370 | SendRequest(
371 | {
372 | action: 'feed',
373 | url: url,
374 | count: 1,
375 | index: 0,
376 | },
377 | function( res )
378 | {
379 | if ( res.items[0].feedtitle == '' || res.items[0].feedlink == '' )
380 | {
381 | MessageBox( i18nGetMessage( 'i18n_0064' ) );
382 | setting.find( '.set_feed' ).focus();
383 | setting.find( '.feed_append' ).removeClass( 'disabled' );
384 |
385 | setting.find( '.rsssetting_items .kinditems' ).last().activity( false );
386 | }
387 | else
388 | {
389 | feedchange = true;
390 | cp.param['urls'].push( { url: res.url, title: res.items[0].feedtitle } );
391 | setting.find( '.rsssetting_apply' ).removeClass( 'disabled' )
392 | .end()
393 | .find( '.set_feed' ).val( '' ).focus();
394 |
395 | // タイトル未設定の場合はフィードのタイトルを設定
396 | var tit = setting.find( '.set_title' );
397 |
398 | if ( ( tit.val() == 'RSS' || tit.val() == '' ) && res.items[0].feedtitle )
399 | {
400 | tit.val( res.items[0].feedtitle );
401 | }
402 |
403 | FeedList();
404 |
405 | setting.find( '.rsssetting_items .kinditems' ).last().activity( false );
406 | }
407 | }
408 | );
409 |
410 | e.stopPropagation();
411 | } );
412 |
413 | ////////////////////////////////////////
414 | // 分類部クリック処理
415 | ////////////////////////////////////////
416 | setting.find( '.kind' ).click( function( e ) {
417 | var img_off = 'icon-play';
418 | var img_on = 'icon-arrow_down';
419 |
420 | if ( $( this ).find( '> span' ).hasClass( img_on ) )
421 | {
422 | $( this ).find( '> span' ).removeClass( img_on ).addClass( img_off )
423 | .end()
424 | .next().slideUp( 0 );
425 | }
426 | else
427 | {
428 | $( this ).find( '> span' ).removeClass( img_off ).addClass( img_on )
429 | .end()
430 | .next().slideDown( 200 );
431 | }
432 |
433 | e.stopPropagation();
434 | } );
435 | }
436 |
437 | ////////////////////////////////////////////////////////////
438 | // 終了処理
439 | ////////////////////////////////////////////////////////////
440 | this.stop = function() {
441 | if ( tm != null )
442 | {
443 | clearTimeout( tm );
444 | tm = null;
445 | }
446 | };
447 | }
448 |
--------------------------------------------------------------------------------