// ==UserScript== // @name [PseudoTweetDeck] HomeTL/List/User/Searchページの自動更新と既読管理 // @namespace http://coltpythonkingcobra.g1.xrea.com/pseudoTweetdeck/ // @version 1.7.12302100 // @description TwitterWEB(X)の各種ページの自動更新(停止可能)、タイトル文字列の置換と絶対時間表示、既読管理、キーワードミュートなどを行う // @author @PseudoTwDk // @match https://twitter.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=twitter.com // @run-at document-idle // @grant none // ==/UserScript== //バージョン情報(ヘルプ・コンフィグ表示用) const VERSION_INFO = "1.7.12302100"; /************************************************************ ローカル保存データの読み書き関連 ************************************************************/ //配布ページURL const PSEUDO_URL = "http://coltpythonkingcobra.g1.xrea.com/pseudoTweetdeck/"; //ローカルストレージのオブジェクトアクセス用キー文字列 const LOCAL_DATA_KEY = "PseudoTwDk_JSON"; //リロード時間記録のキー(複数タブで同時にアクセスされる可能性があるので処理時間短縮のためオブジェクト型ではなく直接ローカルストレージに読み書きする) const FORCEUPDATE_HEADER = "PseudoTwDk_Reload"; //デバッグトレースデータの保存ヘッダ const DEBUG_TRACE_HEADER = "PseudoTwDk_TRACE"; //ローカルストレージ読み書き時のシステム分類キー const KEY_SYSTEM = "SYSTEM"; //グローバル定義時用の汎用カウンタ var gi_defIdx = 0; /* localStorage保存キー */ //システムで一意のもの const COLORMODE_HEADER = "ColorThemeMode";// カラーモード const CHGTIME_HEADER = "ChangeTimestamp";// タイムスタンプの置換 const READCOUNT_HEADER = "ReadPointCount";// 既読ポイント数 const READCHK_HEADER = "ReadPointEnable";// 既読マークの有効無効 const EDITHIDE_HEADER = "HideEditControl";// ツイート欄の非表示 const EDITCLOSE_HEADER = "CloseAfterTweet";// 新規ツイート完了後にツイート欄を非表示にする const NEWTWDISP_HEADER = "DispNewTwHeader";// 上部の新着数表示 const NEWTWCOUNT_HEADER = "DispNewTwCount";// 上部の新着数表示非表示時にエディットON/OFFボタンの横に出す const RECVTWCOUNT_HEADER = "DispRecvTwCount";// 読込件数をエディットON/OFFボタンの横に出す const CLICKNEW_HEADER = "AutoClickNewTw";// 上部の新着を自動的に押す const POPUPTIME_HEADER = "PopupDispTime";// ポップアップを表示する時間 const ENDOMTIME_HEADER = "EnableDOMTime";// レコード更新時間を非アクティブでも表示 const NOCOUNTDN_HEADER = "NoCountDownDisp";// カウントダウンを表示しない const NODISPSAME_HEADER = "NoDispSameTw";// 同一ツイートのRTを並べない const HDOPACITY_HEADER = "HeaderOpacity";// 情報表示部+ボタンの不透明度 const MANTRIGNEW_HEADER = "ManTrigNewTw";// 更新直後に新着表示が出たら押す const IMAGENEW_HEADER = "OpenImageNewTab";// 画像サムネイル左クリックで別タブ表示 const IMAGEORG_HEADER = "OpenImageNewOrg";// 画像サムネイル左クリック時のorig/large const LOCKTIME_HEADER = "ReloadLockTime";// 強制リロードが連続しない排他時間 const IDLESHORT_HEADER = "IdleShortTimer";// 短周期タイマを停止するまでの時間 const IDLEDELAY_HEADER = "IdeleDelayTimer";// 短周期タイマ停止後に遅延ワンショットを行う回数 const USESCROLL_HEADER = "UseScrollEvent";// スクロールイベントを契機に短周期処理を行う const INITWAIT_HEADER = "InitialWait";// 起動待ち合わせ時間 const SHORTINTVL_HEADER = "ShortInterval";// 短周期タイマのインターバル const ONTOPWAIT_HEADER = "OnTopUpdWait";// 最上部にスクロールを戻した直後のトリガ const RELOADWAIT_HEADER = "ReloadWait";// 強制リロード待ち時間 const CHKENAOP_HEADER = "CheckBoxOpaEn";// チェックボックス有効時の不透明度 const CHKDISOP_HEADER = "CheckBoxOpaDs";// チェックボックス無効時の不透明度 const INFOWIDTH_HEADER = "InfoAreaWidth";// 情報表示部の幅 const INFOHEIGHT_HEADER = "InfoAreaHeight";// 情報表示部の高さ const FONTTEXT_HEADER = "FontTextSize";// 表示部のフォントサイズ const FONTBTN_HEADER = "FontButtonSize";// ボタンのフォントサイズ const BGCYCLE_HEADER = "BackgroundCycle";// 既読背景色パターンの繰り返しタイプ const HELPPOPUP_HEADER = "DispHelpPopup";// ヘルプツールチップの表示 const SEACSS_HEADER = "SearchCSSExt";// 検索ページ更新時にCSSを無効にする const SEACSSW_HEADER = "SearchCSSWait";// 検索ページ更新時のCSS無効待ち時間 const SEATITLE_HEADER = "SearchTitle";// 検索ページのタブタイトルを短縮する const COUNTPOS_HEADER = "CountPosition";// 新着/受信件数表示の位置 const DISKEYEV_HEADER = "DisableKeyEvent";// ショートカットキーイベントを抑止 //URL個別のキーとなるもの const INTERVAL_HEADER = "UpdateInterval";// 自動更新インターバル const CHKCOLOR_HEADER = "CheckedBgType";// 既読背景色の表示タイプ const MANUAL_HEADER = "UpdateHoldTime";// 更新後の禁止期間 const RELOAD_HEADER = "ReloadInterval";// 強制リロードインターバル const AUTOOFF_HEADER = "AutoOffMode";// 強制AutoOFFモード const IDLETM_HEADER = "ShortTimerIdle";// 短周期タイマを都度停止するか const MEDIA_HEADER = "MediaDispType";// メディアサムネイル表示サイズ const NOTRT_HEADER = "NotDispRtQuote";// RT&Quoteの非表示 const NOTICON_HEADER = "NotDispExtIcon";// 下部アイコン類の非表示 const CONTDLY_HEADER = "ContinuousDelay";// 新着積み上げの遷移待ち時間 const CONTRET_HEADER = "ContinuousRetTm";// 新着積み上げの戻り待ち時間 const CONTDOMW_HEADER = "ContinuousDOMWait";// 新着積み上げのDOM監視時間 const CONTDOMC_HEADER = "ContinuousDOMCycle";// 新着積み上げのDOM監視サイクル数 const CONTPOPUP_HEADER = "ContinuousPopup";// 新着積み上げ動作時のポップアップ表示 const FINDPOPUP_HEADER = "FindModePopup";// 既読マーク捜索モードのポップアップ表示 const FINDINTVAL_HEADER = "FindModeDelay";// 既読マーク捜索モードの待ち時間 const SCRTOTOPPOPUP_HEADER = "ScrToTopPopup";// スクロールを先頭に戻す時のポップアップ表示 const SCRTOPMKPOPUP_HEADER = "ScrTopMkPopup";// スクロール先頭で既読マークモードのポップアップ表示 const ENABLENGWORD_HEADER = "EnableNGWord";// NGワードを有効にする //システム全体とURL個別の両方で使われるもの const NGWORDDATA_HEADER = "NGWord";// NGワード(文字列の配列形式) //ボタンの表示非表示設定 var ENABLEBUTTON_HEADER = []; //ボタン有効 //ボタンへの割り付け設定 var SCRTOTOP_HEADER = [];// 先頭にスクロール var RESSRTTMR_HEADER = [];// 短周期処理のワンショット実施 var AUTOMARK_HEADER = [];// 既読ポイント設定 var CLRNEWTW_HEADER = [];// 新着の消去待ち var MANTRIG_HEADER = [];// 手動更新 var CONTNEW_HEADER = [];// 新着積み上げ更新 var FINDMODE_HEADER = [];// 既読マーク捜索 var SCRTOPMK_HEADER = [];// スクロール先頭で既読ポイント設定 //表示部の左右ボタン左右クリック設定 const CON_BUTTON_LL = 0; //左ボタン左クリック const CON_BUTTON_LR = 1; //左ボタン右クリック const CON_BUTTON_ML = 2; //中ボタン左クリック const CON_BUTTON_MR = 3; //中ボタン右クリック const CON_BUTTON_RL = 4; //右ボタン左クリック const CON_BUTTON_RR = 5; //右ボタン右クリック const CON_BUTTON_CL = 6; //件数表示部左クリック const CON_BUTTON_CR = 7; //件数表示部右クリック const MAX_CON_BUTTON = 8; //(enum値最大値+1) for(gi_defIdx=0; gi_defIdx 0 ){ var ret; ret = [].concat(val); return ret; }else{ return []; } } } } //ローカル保存データのレコード書き込み function saveSetting( key1, key2, value, noLoadObject=false, noSaveObject=false){ //key1 : 保存項目名 //key2 : URL/PATH または"SYSTEM" //value : 保存値 //noLoadObject : true=ローカル保存データを読み込まずに既に読み込まれているデータを対象とする(連続処理時用、先にloadStorageData()を実施しておくこと) //noSaveObject : true=ローカル保存データを最後に書き込まない(連続処理時用、次処理でsaveStorageData()を実施しておくこと) /* 旧データ形式 var k = key1; if( key2 != KEY_SYSTEM ){ k += key2; } return window.localStorage.setItem(k,value); */ //リロード時間記録だけは直でアクセスする if( key1 == FORCEUPDATE_HEADER ){ return window.localStorage.setItem(key1,value); } if( ! noLoadObject ){ //他のタブでも更新しているので読み込んでから更新する loadStorageData(); } var obj = gobj_localData[key2]; if( obj === null || obj === undefined ){ obj = new Object; } if( key1 != NGWORDDATA_HEADER ){ obj[key1] = "" + value; }else{ //NGワードだけは配列型なのでディープクローンを代入する if( value !== null && value !== undefined && value.length > 0 ){ obj[key1] = JSON.parse(JSON.stringify(value)); }else{ delete obj[key1]; } } gobj_localData[key2] = JSON.parse(JSON.stringify(obj)); if( ! noSaveObject ){ //localStorageに格納する saveStorageData(); } } //ローカル保存データのレコード削除 function removeSetting( key1, key2, noLoadObject=false, noSaveObject=false){ //key1 : 保存項目名 //key2 : URL/PATH または"SYSTEM" //noLoadObject : true=ローカル保存データを読み込まずに既に読み込まれているデータを対象とする(連続処理時用、先にloadStorageData()を実施しておくこと) //noSaveObject : true=ローカル保存データを最後に書き込まない(連続処理時用、次処理でsaveStorageData()を実施しておくこと) //リロード時間記録だけは直でアクセスする if( key1 == FORCEUPDATE_HEADER ){ return window.localStorage.removeItem(key1); } if( ! noLoadObject ){ //他のタブでも更新しているので読み込んでから更新する loadStorageData(); } var obj = gobj_localData[key2]; if( obj === null || obj === undefined ){ return; } delete gobj_localData[key2][key1]; if( ! noSaveObject ){ //localStorageに格納する saveStorageData(); } } /************************************************************ デバッグトレース関連定義 ************************************************************/ //デバッグモードを有効にする場合の記録キー const DEBUG_MODE_HEADER = "DEBUG_Mode"; const DEBUG_WINDOW_SIZE = "DEBUG_Window_Size"; const DEBUG_WINDOW_FILTER = "DEBUG_Window_Filter"; var DEBUG_MODE = 0; var debugWindowSize = 2;//(0:OFF 1:S 2:M 3:L 4:MAX) //デバッグモード(兼、デバッグウィンドウサイズ) (function(){ var ret = loadSetting(DEBUG_MODE_HEADER, KEY_SYSTEM); if( ret !== null && ret > 0 ) DEBUG_MODE = 1; })(); //ログ種別 const LOG_NORM = 0; const LOG_SYS = 1; const LOG_DIAG = 2; const LOG_SHRT = 3; const LOG_ERR = 4; const LOG_DOM = 5; const LOG_WARN = 6; const LOG_OPE = 7; const LOG_TRC = 8 const LOG_MAX = 9;//(定義enum+1) //Filter表示用ログタイプ文字列 const debugFilterText = ["LOG_NORM","LOG_SYS","LOG_DIAG","LOG_SHRT","LOG_ERR","LOG_DOM","LOG_WARN","LOG_OPE","LOG_TRC"]; //隠しセル(コピーペーストでは乗ってくる)文字列 const debugLogHidden = ["NORM","SYS_","DIAG","SHRT","ERR_","DOM_","WARN","OPE_","TRC_"]; //ログタイプ別の色設定 const debugFilterColor = ["#FFFFFF","#7F7FFF","#7FFF7F","#7FFFFF","#FF7F7F","#FF7FFF","#FFFF7F","#9F9F9F","#FFAFAF"]; //表示設定初期値 const defaultDebugFilterEnabled = [true,true,true,true,true,true,true,true,true]; //初期値をディープクローン(代入だと参照が移ってしまうので初期状態の値と比較するため) var debugFilterEnabled = [].concat(defaultDebugFilterEnabled); //トレース内容のオブジェクトの配列 var debugTextArray = []; //Filter設定画面のボタン色 const COLOR_BUTTON_ENA_FORE = "rgb(255,255,255)"; const COLOR_BUTTON_ENA_BACK = "rgb(127,127,127)"; const COLOR_BUTTON_DIS_FORE = "rgb(95,95,95)"; const COLOR_BUTTON_DIS_BACK = "rgb(63,63,63)"; const MAX_DEBUG_RECS = 1000; const DEBUG_MIN_HEIGHT = ["","140px","270px","540px",(window.innerHeight - 12) + "px"]; //親画面にホイールのイベントが伝わってしまうのを防ぐ処理の解除タイマ var tmrHoldScroll = null; /************************************************************ 色関連定義 ************************************************************/ //カラーモード ダークテーマ・ブラックテーマ=1, ライトテーマ=0 const DEF_COLOR_MODE = 1; var COLOR_MODE = DEF_COLOR_MODE;//※システムコンフィグで変更可能 //後続の色定義はカラーモードによって定義を切り替えているので先にローカル保存データから読み込む (function(){ var v = loadSetting( COLORMODE_HEADER, KEY_SYSTEM ); if( v !== null ) COLOR_MODE = ( Number(v) == 0 ) ? 0: 1; })(); /***** ※色関係の定義を変えたらヘルプダイアログ中の説明文なども変える *****/ //※(COLOR_MODE)?暗テーマ時の色:明テーマ時の色 const COLOR_GRAY = (COLOR_MODE)?"rgba(255,255,255,0.3)":"rgba(191,191,191,0.2)";//初期色(非稼働) const COLOR_BLACK = "rgba(0,0,0,1.0)"; const COLOR_WHITE = "rgba(255,255,255,1.0)"; const COLOR_LIGHT_BLACK = "rgba(15,15,15,0.75)"; const COLOR_LIGHT_WHITE = "rgba(239,239,239,0.75)"; const COLOR_CLEAR = "rgba(0,0,0,0.0)"; const COLOR_BORDER = (COLOR_MODE)?"rgba(31,31,31,0.4)":"rgba(223,223,223,0.2)";//表示部枠の色 const COLOR_FGCOLOR = (COLOR_MODE)?COLOR_WHITE:COLOR_BLACK;//汎用文字色 const COLOR_BGCOLOR = (COLOR_MODE)?COLOR_BLACK:COLOR_WHITE;//汎用背景色 const COLOR_BASE = (COLOR_MODE)?"rgba(31,31,31,1.0)":"rgba(223,223,223,1.0)";//汎用ベース色 const COLOR_RECVCOUNT = (COLOR_MODE)?COLOR_LIGHT_WHITE:COLOR_LIGHT_BLACK;//受信件数表示フォント色 const COLOR_TOOLTIPS_FGCOLOR = (COLOR_MODE)?COLOR_WHITE:COLOR_BLACK;//ヘルプツールチップの文字色 const COLOR_TOOLTIPS_BGCOLOR = (COLOR_MODE)?COLOR_BLACK:COLOR_WHITE;//ヘルプツールチップの背景色 const COLOR_TOOLTIPS_BORDER = (COLOR_MODE)?"rgba(31,31,31,0.4)":"rgba(223,223,223,0.2)";//ヘルプツールチップの枠色 const COLOR_SOLID_GRAY = (COLOR_MODE)?"rgba(63,63,63,1.0)":"rgba(191,191,191,1.0)";//不透明グレー const COLOR_POPUP_FGCOLOR = (COLOR_MODE)?COLOR_WHITE:COLOR_BLACK;//ポップアップの文字色 const COLOR_POPUP_BGCOLOR_MARK = (COLOR_MODE)?COLOR_SOLID_GRAY:COLOR_SOLID_GRAY;//ポップアップの背景色(先頭記事に既読マーク) const COLOR_POPUP_BGCOLOR_TOPM = (COLOR_MODE)?"rgba(52,52,52,1.0)":"rgba(181,181,181,1.0)";//ポップアップの背景色(スクロール先頭で既読マーク) const COLOR_POPUP_BGCOLOR_TTOP = (COLOR_MODE)?"rgba(62,62,62,1.0)":"rgba(171,171,171,1.0)";//ポップアップの背景色(先頭にスクロール) const COLOR_POPUP_BGCOLOR_CONT = (COLOR_MODE)?"rgba(72,72,72,1.0)":"rgba(161,161,161,1.0)";//ポップアップの背景色(新着積み上げ更新) const COLOR_POPUP_BGCOLOR_FIND = (COLOR_MODE)?"rgba(82,82,82,1.0)":"rgba(151,151,151,1.0)";//ポップアップの背景色(既読マーク捜索モード) const COLOR_COUNT_BG = COLOR_BASE;//新着・受信件数表示部の背景色 //情報表示部ボタンの色 const INFOBUTTON_BORDER_COLOR = "transparent";//情報表示部に配置されるボタンコントロールの枠色 "transparent"=透明 const INFOBUTTON_FORE_COLOR = (COLOR_MODE)?COLOR_WHITE:COLOR_BLACK;//同上文字色 const INFOBUTTON_BG_COLOR = (COLOR_MODE)?COLOR_BLACK:COLOR_WHITE;//同上背景色 //情報表示部の色 const COLOR_UPDATE = (COLOR_MODE)?"rgba(191,63,63,1.0)":"rgba(127,0,0,1.0)";//自動更新トリガ時の色 const COLOR_UPSOON = (COLOR_MODE)?"rgba(191,191,63,1.0)":"rgba(127,127,0,1.0)";//自動更新トリガまで10秒以内の色 const COLOR_ACTIVE = (COLOR_MODE)?"rgba(63,191,63,1.0)":"rgba(0,127,0,1.0)";//自動更新モード有効時の色 const COLOR_PAUSED = (COLOR_MODE)?"rgba(63,63,191,1.0)":"rgba(0,0,127,1.0)";//自動更新の一時停止状態の色 const COLOR_HOLDTM = (COLOR_MODE)?"rgba(63,191,191,1.0)":"rgba(0,127,127,1.0)";//手動更新抑止期間の色 const COLOR_RELOAD = (COLOR_MODE)?"rgba(191,63,191,1.0)":"rgba(127,0,127,1.0)";//強制自動リロード10秒前の色 //インターバル設定ボタンの色 const COLOR_INT_DISABL = (COLOR_MODE)?"rgba(127,127,127,0.5)":"rgba(191,191,191,0.5)";//初期値(非稼働) const COLOR_INT_UPDATE = (COLOR_MODE)?"rgba(191,63,63,1.0)":"rgba(127,0,0,1.0)";//自動更新トリガ時の色 const COLOR_INT_UPSOON = (COLOR_MODE)?"rgba(191,191,63,1.0)":"rgba(127,127,0,1.0)";//自動更新トリガまで10秒以内の色 const COLOR_INT_ACTIVE = (COLOR_MODE)?"rgba(63,191,63,1.0)":"rgba(0,127,0,1.0)";//自動更新モード有効時の色 const COLOR_INT_PAUSED = (COLOR_MODE)?"rgba(63,63,191,1.0)":"rgba(0,0,127,1.0)";//自動更新の一時停止状態の色 const COLOR_INT_HOLDTM = (COLOR_MODE)?"rgba(63,191,191,1.0)":"rgba(0,127,127,1.0)";//手動更新抑止期間の色 const COLOR_INT_RELOAD = (COLOR_MODE)?"rgba(191,63,191,1.0)":"rgba(127,0,127,1.0)";//強制自動リロード10秒前の色 //ヘルプボタンの色 const COLOR_HLP_DISABL = (COLOR_MODE)?"rgba(127,127,127,0.5)":"rgba(191,191,191,0.5)";//初期値(非稼働) const COLOR_HLP_UPDATE = (COLOR_MODE)?"rgba(191,63,63,1.0)":"rgba(127,0,0,1.0)";//自動更新トリガ時の色 const COLOR_HLP_UPSOON = (COLOR_MODE)?"rgba(191,191,63,1.0)":"rgba(127,191,0,1.0)";//自動更新トリガまで10秒以内の色 const COLOR_HLP_ACTIVE = (COLOR_MODE)?"rgba(63,191,63,1.0)":"rgba(0,127,0,1.0)";//自動更新モード有効時の色 const COLOR_HLP_PAUSED = (COLOR_MODE)?"rgba(63,63,191,1.0)":"rgba(0,0,127,1.0)";//自動更新の一時停止状態の色 const COLOR_HLP_HOLDTM = (COLOR_MODE)?"rgba(63,191,191,1.0)":"rgba(0,127,127,1.0)";//手動更新抑止期間の色 const COLOR_HLP_RELOAD = (COLOR_MODE)?"rgba(191,63,191,1.0)":"rgba(127,0,127,1.0)";//強制自動リロード10秒前の色 //短周期タイマ変更ボタンの色 const COLOR_ALW_UPDATE = (COLOR_MODE)?"rgba(191,63,63,0.5)":"rgba(127,0,0,0.5)";//短周期タイマ常時稼動モード状態で自動更新トリガ時の色 const COLOR_ALW_UPSOON = (COLOR_MODE)?"rgba(191,191,63,0.5)":"rgba(127,127,0,0.5)";//短周期タイマ常時稼動モード状態で自動更新トリガまで10秒以内の色 const COLOR_ALW_ACTIVE = (COLOR_MODE)?"rgba(63,191,63,0.5)":"rgba(0,127,0,0.5)";//短周期タイマ常時稼動モード状態で自動更新モード有効時の色 const COLOR_ALW_PAUSED = (COLOR_MODE)?"rgba(63,63,191,0.5)":"rgba(0,0,127,0.5)";//短周期タイマ常時稼動モード状態で自動更新の一時停止状態の色 const COLOR_ALW_HOLDTM = (COLOR_MODE)?"rgba(63,191,191,0.5)":"rgba(0,127,127,0.5)";//短周期タイマ常時稼動モード状態で手動更新抑止期間の色 const COLOR_ALW_RELOAD = (COLOR_MODE)?"rgba(191,63,191,0.5)":"rgba(127,0,127,0.5)";//短周期タイマ常時稼動モード状態で強制自動リロード10秒前の色 const COLOR_IDL_DISABL = (COLOR_MODE)?"rgba(127,127,127,0.5)":"rgba(191,191,191,0.5)";//短周期タイマの一時停止状態の色 const COLOR_IDL_UPDATE = (COLOR_MODE)?"rgba(191,63,63,1.0)":"rgba(127,0,0,1.0)";//短周期タイマ適宜停止モード状態で自動更新トリガ時の色 const COLOR_IDL_UPSOON = (COLOR_MODE)?"rgba(191,191,63,1.0)":"rgba(127,127,0,1.0)";//短周期タイマ適宜停止モード状態で自動更新トリガまで10秒以内の色 const COLOR_IDL_ACTIVE = (COLOR_MODE)?"rgba(63,191,63,1.0)":"rgba(0,127,0,1.0)";//短周期タイマ適宜停止モード状態で自動更新モード有効時の色 const COLOR_IDL_PAUSED = (COLOR_MODE)?"rgba(63,63,191,1.0)":"rgba(0,0,127,1.0)";//短周期タイマ適宜停止モード状態で自動更新の一時停止状態の色 const COLOR_IDL_HOLDTM = (COLOR_MODE)?"rgba(63,191,191,1.0)":"rgba(0,127,127,1.0)";//手動更新抑止期間の色短周期タイマ適宜停止モード状態で const COLOR_IDL_RELOAD = (COLOR_MODE)?"rgba(191,63,191,1.0)":"rgba(127,0,127,1.0)";//短周期タイマ適宜停止モード状態で強制自動リロード10秒前の色 //自動更新ON/OFFボタンの色 const COLOR_AUT_DISABL = (COLOR_MODE)?"rgba(127,127,127,0.5)":"rgba(191,191,191,0.5)";//自動更新OFF時の色 const COLOR_AUT_UPDATE = (COLOR_MODE)?"rgba(191,63,63,1.0)":"rgba(127,0,0,1.0)";//自動更新ON時で自動更新トリガ時の色 const COLOR_AUT_UPSOON = (COLOR_MODE)?"rgba(191,191,63,1.0)":"rgba(127,127,0,1.0)";//自動更新ON時で自動更新トリガまで10秒以内の色 const COLOR_AUT_ACTIVE = (COLOR_MODE)?"rgba(63,191,63,1.0)":"rgba(0,127,0,1.0)";//自動更新ON時で自動更新モード有効時の色 const COLOR_AUT_PAUSED = (COLOR_MODE)?"rgba(63,63,191,1.0)":"rgba(0,0,127,1.0)";//自動更新ON時で自動更新の一時停止状態の色 const COLOR_AUT_HOLDTM = (COLOR_MODE)?"rgba(63,191,191,1.0)":"rgba(0,127,127,1.0)";//自動更新ON時で手動更新抑止期間の色 const COLOR_AUT_RELOAD = (COLOR_MODE)?"rgba(191,63,191,1.0)":"rgba(127,0,127,1.0)";//自動更新ON時で強制自動リロード10秒前の色 //チェックボックスの不透明度 const DEF_CHECKBOX_ENABLE_OPACITY = "0.5"; var CHECKBOX_ENABLE_OPACITY = DEF_CHECKBOX_ENABLE_OPACITY;//※システムコンフィグで変更可能 const DEF_CHECKBOX_DISABLE_OPACITY = "0.0"; var CHECKBOX_DISABLE_OPACITY = DEF_CHECKBOX_DISABLE_OPACITY;//※システムコンフィグで変更可能 //既読ポイントとしてチェックしたアーティクルの背景色 const DEF_READ_COLOR_ENABLED1 = (COLOR_MODE)?"rgba(255,255,255,0.15)":"rgba(0,0,0,0.10)"; const DEF_READ_COLOR_ENABLED2 = (COLOR_MODE)?"rgba(255,255,255,0.20)":"rgba(0,0,0,0.20)"; const DEF_READ_COLOR_ENABLED3 = (COLOR_MODE)?"rgba(255,255,255,0.25)":"rgba(0,0,0,0.30)"; const DEF_READ_COLOR_ENABLED4 = (COLOR_MODE)?"rgba(255,255,255,0.30)":"rgba(0,0,0,0.40)"; var READ_COLOR_ENABLED = []; var READ_COLOR_ENABLED1 = []; var READ_COLOR_ENABLED2 = []; var READ_COLOR_ENABLED3 = []; var READ_COLOR_ENABLED4 = []; //既読ポイント背景色の切り替えパターン数 const gi_readColorPattern = 10;//※(READ_COLOR_ENABLED1,2,3,4)の配列要素数を設定 //既読ポイント背景色の繰り返しパターンType数(READ_COLOR_ENABLED1,2,3,4) const READ_COLOR_CYCLE = 4;//Type数 //既読ポイント背景色パターンType1 READ_COLOR_ENABLED1 = [ DEF_READ_COLOR_ENABLED1, DEF_READ_COLOR_ENABLED1, DEF_READ_COLOR_ENABLED1, DEF_READ_COLOR_ENABLED1, DEF_READ_COLOR_ENABLED1, DEF_READ_COLOR_ENABLED1, DEF_READ_COLOR_ENABLED1, DEF_READ_COLOR_ENABLED1, DEF_READ_COLOR_ENABLED1, DEF_READ_COLOR_ENABLED1, ]; //既読ポイント背景色パターンType2 READ_COLOR_ENABLED2 = [ DEF_READ_COLOR_ENABLED3, DEF_READ_COLOR_ENABLED2, (COLOR_MODE)?"rgba(255,191,191,0.2)":"rgba(255,0,0,0.1)", (COLOR_MODE)?"rgba(191,255,191,0.2)":"rgba(0,255,0,0.1)", (COLOR_MODE)?"rgba(191,191,255,0.2)":"rgba(0,0,255,0.1)", DEF_READ_COLOR_ENABLED3, DEF_READ_COLOR_ENABLED2, (COLOR_MODE)?"rgba(191,255,255,0.2)":"rgba(0,255,255,0.1)", (COLOR_MODE)?"rgba(255,191,255,0.2)":"rgba(255,0,255,0.1)", (COLOR_MODE)?"rgba(255,255,191,0.2)":"rgba(255,255,0,0.1)", ]; //既読ポイント背景色パターンType3 READ_COLOR_ENABLED3 = [ DEF_READ_COLOR_ENABLED4, DEF_READ_COLOR_ENABLED3, (COLOR_MODE)?"rgba(191,255,255,0.3)":"rgba(0,255,255,0.2)", (COLOR_MODE)?"rgba(255,191,255,0.3)":"rgba(255,0,255,0.2)", (COLOR_MODE)?"rgba(255,255,191,0.3)":"rgba(255,255,0,0.2)", DEF_READ_COLOR_ENABLED4, DEF_READ_COLOR_ENABLED3, (COLOR_MODE)?"rgba(255,191,191,0.3)":"rgba(255,0,0,0.2)", (COLOR_MODE)?"rgba(191,255,191,0.3)":"rgba(0,255,0,0.2)", (COLOR_MODE)?"rgba(191,191,255,0.3)":"rgba(0,0,255,0.2)", ]; //既読ポイント背景色パターンType4 READ_COLOR_ENABLED4 = [ DEF_READ_COLOR_ENABLED3, DEF_READ_COLOR_ENABLED2, DEF_READ_COLOR_ENABLED3, DEF_READ_COLOR_ENABLED2, DEF_READ_COLOR_ENABLED3, DEF_READ_COLOR_ENABLED2, DEF_READ_COLOR_ENABLED3, DEF_READ_COLOR_ENABLED2, DEF_READ_COLOR_ENABLED3, DEF_READ_COLOR_ENABLED2, ]; /************************************************************ 各種const定義 コンフィグ・システムコンフィグ項目・初期値 ************************************************************/ //※ const gx_defaultXXXX = xxx; / var gx_xXXX = gx_defaultXXXX; になっている項目は(ほぼ全て)コンフィグまたはシステムコンフィグで変更すると保存されます //コンフィグ・システムコンフィグで設定変更可能で保存される項目にはコメントをつけておきます //これらの項目は一度設定しておけばバージョンアップでスクリプトソースを丸ごと差し換えても保存値で動作します(直接その項目に大幅な仕様変更がある場合を除く) //短周期タイマを一定時間後に停止する=1, 停止させず回ったままにする=0 (短周期タイマ切り替えボタンのクリックで変更可能) const gi_defalutIdleShortTimer = 1; var gi_idleShortTimer = gi_defalutIdleShortTimer;//※ボタン操作とコンフィグで変更可能 //相対時間を絶対時間表記にする=1, しない=0 const gi_defaultReplaceTimeStamp = 1; var gi_replaceTimeStamp = gi_defaultReplaceTimeStamp;//※システムコンフィグで変更可能 //自動更新OFFモード スクロール位置やエディットのフォーカスによらず強制OFF=1, 従来の動作=0(自動更新ON/OFF切り替えボタンのクリックで変更可能) const gi_defaultModeAutoOff = 0; var gi_modeAutoOff = gi_defaultModeAutoOff;//※ボタン操作とコンフィグで変更可能 //Homeで上部の新着ツイートありの表示を勝手に押す=1, 押さない=0 const gi_defaultAutoClickNewTweet = 0; var gi_autoClickNewTweet = gi_defaultAutoClickNewTweet;//※システムコンフィグで変更可能 //Homeで上部の新着ツイートありの表示を非表示にする=1, 非表示にしない=0(エディット表示切り替えボタンの右クリックで変更可能) const gi_defaultHideNumberNewTweet = 1; var gi_hideNumberNewTweet = gi_defaultHideNumberNewTweet;//※ボタン操作とコンフィグで変更可能 //Homeで上部の新着ツイート表示数を非表示設定の時にエディット切り替えボタン横に数値を出す const gi_defaultDispNumberNewTweetCount = 1; var gi_dispNumberNewTweetCount = gi_defaultDispNumberNewTweetCount;//※コンフィグで変更可能 //読込件数表示をエディット切り替えボタン横に数値を出す const gi_defaultDispNumberRecvTweetCount = 1; var gi_dispNumberRecvTweetCount = gi_defaultDispNumberRecvTweetCount;//※コンフィグで変更可能 //ポップアップメッセージを出しておく時間(秒) 出さない場合は0にする const gi_defaultDisplayPopupCloseTimeSec = 5; var gi_displayPopupCloseTimeSec = gi_defaultDisplayPopupCloseTimeSec;//※システムコンフィグで変更可能 var gi_displayHelpToolTipsPopupCloseTimeSec = gi_defaultDisplayPopupCloseTimeSec * 2;//mouseleaveですぐ消えるが、万一の消え残り対策 //レコード更新の最終タイムスタンプを自動更新OFFでも表示する=1, 表示しない=0 const gi_defaultEnableDomTimeAutoOff = 1; var gi_enableDomTimeAutoOff = gi_defaultEnableDomTimeAutoOff;//※システムコンフィグで変更可能 //情報表示部のカウントダウンを表示しない=1, 表示する=0 const gi_defaultNoCountDownDisp = 0; var gi_noCountDownDisp = gi_defaultNoCountDownDisp;//※システムコンフィグで変更可能 //既読ポイント用のチェックボックスを表示する=1, 表示しない=0 const gi_defaultEnableReadPointCheckBox = 1; var gi_enableReadPointCheckBox = gi_defaultEnableReadPointCheckBox;//※システムコンフィグで変更可能 //同一のアーティクルをTLに複数表示しない(RTが並ばなくなる)表示しない=1, 表示する=0 const gi_defaultNotDispSameArticle = 1; var gi_notDispSameArticle = gi_defaultNotDispSameArticle;//※システムコンフィグで変更可能 //Home上部のツイート欄を非表示にする=1, 表示したままにする=0 (エディット表示切り替えボタンクリックで変更可能) const gi_defaultHideEditControl = 1; var gi_hideEditControl = gi_defaultHideEditControl;//※コンフィグで変更可能 //新規ツイート完了後にツイート欄を非表示にする=1, 表示したままにする=0 const gi_defaultNewTweetCompleteCloseEdit = 1; var gi_newTweetCompleteCloseEdit = gi_defaultNewTweetCompleteCloseEdit;//※コンフィグで変更可能 //新規ツイート後にエディットを戻すまでのラグ時間 const gi_newTweetCompleteWaitMs = 1000; //新規ツイート後の処理が何度も走らないようにする排他時間 const gi_newTweetCompleteHoldTimeMs = 10000; //新規ツイート完了後にツイート欄を非表示にしたタイムスタンプ var gobj_newTweetCompleteTime = new Date(); //表示部+ボタンの不透明度(透明0.0〜1.0不透明 ※多分0.1刻みくらいでしか変化しない) const gf_defaultDispUnitOpacity = 1.0; var gf_dispUnitOpacity = gf_defaultDispUnitOpacity;//※システムコンフィグで変更可能 // ************ ボタンコントロールの割り付けデフォルト値 **************** // giA_defaultXXX = [CON_BUTTON_LL,CON_BUTTON_LR,CON_BUTTON_ML,CON_BUTTON_MR,CON_BUTTON_RL,CON_BUTTON_RR,CON_BUTTON_CL,CON_BUTTON_CR]; //表示部をクリックで短周期処理のワンショット実行をする=1, しない=0 const giA_defaultOneShotShortTimer = [0,0,0,0,1,0,0,0]; var giA_oneShotShortTimer = giA_defaultOneShotShortTimer;//※コンフィグで変更可能 //表示部をクリックした時に表示されている最新アーティクルを既読マークする=1, しない=0 const giA_defaultManualUpdateAutoCheck = [1,1,0,1,0,0,0,0]; var giA_manualUpdateAutoCheck = giA_defaultManualUpdateAutoCheck;//※コンフィグで変更可能 //表示部をクリックで通知ページの新着表示を消去する=1, しない=0 const giA_defaultClearNewNotification = [1,0,1,0,1,0,1,0]; var giA_clearNewNotification = giA_defaultClearNewNotification;//※コンフィグで変更可能 //表示部をクリックで手動更新トリガをかける=1, トリガしない=0(但し、更新禁止間隔以内ではトリガしない) const giA_defaultManualUpdateTrigger = [0,1,1,1,0,0,1,0]; var giA_manualUpdateTrigger = giA_defaultManualUpdateTrigger;//※コンフィグで変更可能 //表示部をクリックで手動更新トリガ時に新着を上に積む動作をする=1, しない=0 (※上のgiA_manualUpdateTriggerが有効じゃないと使われません) const giA_defaultUpdateContinuousButton = [0,1,0,0,0,0,1,0]; var giA_updateContinuousButton = giA_defaultUpdateContinuousButton;//※コンフィグで変更可能 //表示部をクリックで既読ポイント捜索モードに入る=1, 入らない=0(※手動更新トリガ・新着上積みとは同時に使えません) const giA_defaultFindReadPointButton = [0,0,0,0,0,1,0,1]; var giA_findReadPointButton = giA_defaultFindReadPointButton;//※コンフィグで変更可能 //表示部をクリックでスクロールを最上部に戻す=1, 戻さない=0 const giA_defaultScrToTopButton = [0,1,1,1,1,0,1,0]; var giA_scrToTopButton = giA_defaultScrToTopButton;//※コンフィグで変更可能 ※giA_defaultScrTopMarkButtonと排他が望ましい //表示部をクリックで次回のスクロール最上部で既読ポイントをつける=1, つけない=0 const giA_defaultScrTopMarkButton = [1,1,0,0,0,1,0,0]; var giA_scrTopMarkButton = giA_defaultScrTopMarkButton;//※コンフィグで変更可能 ※giA_defaultScrToTopButtonと排他が望ましい //表示部ボタンの有効無効設定 有効=1, 無効=0 [BTN1, BTN2, BTN3, BTN4] const giA_defaultEnableButton = [1,1,1,1]; var giA_enableButton = giA_defaultEnableButton;//※コンフィグで変更可能 //表示部のボタンや横の各ボタンhover時にヘルプツールチップを表示する=1, 表示しない=0 const gi_defaultDispToolTipsPopup = 1; var gi_dispToolTipsPopup = gi_defaultDispToolTipsPopup;//※システムコンフィグで変更可能 //新着/受信件数表示の表示位置 非表示=0, 左端=1, 中央=2, 右端=3 const BTN4_POSITION_NONE = 0; const BTN4_POSITION_LEFT = 1; const BTN4_POSITION_MID = 2; const BTN4_POSITION_RIGHT = 3; const gi_defaultCountPosition = BTN4_POSITION_RIGHT; var gi_countPosition = gi_defaultCountPosition;//※システムコンフィグで変更可能 //ショートカットキーの無効化 const gi_defaultDisableKeyEvent = 1; var gi_disableKeyEvent = gi_defaultDisableKeyEvent;//※システムコンフィグで変更可能 //更新トリガした直後の新着表示を自動的に押す=1, 押さない=0 const gi_defaultManualUpdateTriggerNewTweet = 1; var gi_manualUpdateTriggerNewTweet = gi_defaultManualUpdateTriggerNewTweet;//※システムコンフィグで変更可能 //新着を上に積む操作時にポップアップを出す=1, 出さない=0 const gi_defaultUpdateContinuousDispPopup = 1; var gi_updateContinuousDispPopup = gi_defaultUpdateContinuousDispPopup;//※コンフィグで変更可能 //既読マーク捜索モード中にポップアップを出す=1, 出さない=0 const gi_defaultFindModeDispPopup = 1; var gi_findModeDispPopup = gi_defaultFindModeDispPopup;//※コンフィグで変更可能 //次回のスクロール最上部で既読マークモード中にポップアップを出す=1, 出さない=0 const gi_defaultScrTopMarkModeDispPopup = 1; var gi_scrTopMarkModeDispPopup = gi_defaultScrTopMarkModeDispPopup;//※コンフィグで変更可能 //スクロールを先頭に戻す処理中にポップアップを出す=1, 出さない=0 const gi_defaultScrToTopModeDispPopup = 1; var gi_scrToTopModeDispPopup = gi_defaultScrToTopModeDispPopup;//※コンフィグで変更可能 //更新トリガ時新着を上に積む更新でトリガから先頭記事に遷移するまでの待機時間(ms) [ unknown(未使用), Home, List, User、Notification(未使用), Search ] const giA_defaultUpdateContinuousDelayTimeMs = [1000, 250, 500, 500, 1000, 500]; var gi_updateContimuousDelayTimeMs = giA_defaultUpdateContinuousDelayTimeMs[1];//※コンフィグで変更可能 //更新トリガ時新着を上に積む更新で遷移先から戻るまでの待機時間(ms) const gi_defaultUpdateContinuousReturnTimeMs = 500; var gi_updateContinuousReturnTimeMs = gi_defaultUpdateContinuousReturnTimeMs;//※コンフィグで変更可能 //更新トリガ時新着を上に積む更新でタイムラインに戻ってから正否を判定するまでの待機時間(ms) const gi_defaultUpdateContinuousResultTimeMs = 1000; var gi_updateContinuousResultTimeMs = gi_defaultUpdateContinuousResultTimeMs;//※コンフィグで変更可能 //更新トリガ時新着を上に積む更新でレコード更新があがってきてから一定期間が経過したか判定する待ち時間(ms) const gi_defaultUpdateContinuousDOMPastCycle = 5; var gi_updateContinuousDOMPastCycle = gi_defaultUpdateContinuousDOMPastCycle;//※コンフィグで変更可能 //画像サムネイルを左クリックで別タブに画像表示する=1, しない=0 const gi_defaultDisplayImageNewTab = 1; var gi_displayImageNewTab = gi_defaultDisplayImageNewTab;//※システムコンフィグで変更可能 //画像サムネイルを左クリックで別タブに画像表示するときorigで開き次はlargeで開く=1, 常にlargeで開く=0 const gi_defaultDisplayImageTryOrig = 0; var gi_displayImageTryOrig = gi_defaultDisplayImageTryOrig;//※システムコンフィグで変更可能 //画像サムネイル左クリックで前回開いたパス var gstr_lastImagePath = ""; //更新間隔定義(秒)=これを初期値としてコンフィグページで設定変更と保存が可能、最大3600だが強制再起動が先に掛かる可能性あり const gi_updateIntervalMsHome = 30; const gi_updateIntervalMsList = 300; const gi_updateIntervalMsUser = 600; const gi_updateIntervalMsNoti = 15; const gi_updateIntervalMsSear = 180; //更新間隔 [ unknown(未使用), Home, List, User、Notification(新着クリア), Search ] const giA_defaultIntervalMs = [1000, parseInt(gi_updateIntervalMsHome * 1000), parseInt(gi_updateIntervalMsList * 1000), parseInt(gi_updateIntervalMsUser * 1000), parseInt(gi_updateIntervalMsNoti * 1000), parseInt(gi_updateIntervalMsSear * 1000)]//※コンフィグで変更可能 var giA_updateIntervalMs = giA_defaultIntervalMs; //短周期タイマを止めるまでの経過時間(ミリ秒) const gi_defaultShortTimerIdleMs = 1000; var gi_shortTimerIdleMs = gi_defaultShortTimerIdleMs;//※システムコンフィグで変更可能 //短周期タイマを止めた後の遅延ワンショット実施回数 gobjA_delayOneShotShortTimer と giA_delayOneShotShortTimerSec の配列数範囲でのみ設定可能 const gi_defaultShortTimerIdleDelayCount = 0; var gi_shortTimerIdleDelayCount = gi_defaultShortTimerIdleDelayCount;//※システムコンフィグで変更可能 //スクロールイベントで短周期タイマを制御する const gi_defaultUseScrollEvent = 1; var gi_useScrollEvent = gi_defaultUseScrollEvent;//※システムコンフィグで変更可能 //起動時待ち合わせ時間(ミリ秒) const gi_defaultInitWaitMs = 5000; var gi_initWaitMs = gi_defaultInitWaitMs;//※システムコンフィグで変更可能 //短周期タイマの間隔(ミリ秒) const gi_defaultShortIntervalMs = 250; var gi_shortIntervalMs = gi_defaultShortIntervalMs;//※システムコンフィグで変更可能 //スクロール位置が先頭に戻った後の短縮更新待ちあわせ時間(ミリ秒) const gi_defaultOnTopWaitMs = 0; var gi_onTopWaitMs = gi_defaultOnTopWaitMs;//※システムコンフィグで変更可能 //強制リロード時の待ち合わせ時間(ミリ秒) const gi_defaultReloadWaitMs = 5000; var gi_reloadWaitMs = gi_defaultReloadWaitMs;//※システムコンフィグで変更可能 //強制リロード実施間隔初期値(秒)=これを初期値としてコンフィグページで設定変更と保存が可能、最大7200だがTwitter独自の再起動が先に掛かる可能性あり const giA_defaultReloadTimeoutSec = [0, 0, 0, 0, 0, 0 ]; //[ unknown(未使用), Home, List, User、Notification, Search ] var giA_reloadTimeoutSec = giA_defaultReloadTimeoutSec;//※コンフィグで変更可能 //手動で更新をかけない経過時間(秒) ※自動更新インターバルの最小値としても使われる ※最後に更新をかけた時からこの設定時間以内は更新トリガ発行しない const gi_defaultManualUpdateIntervalSec = 5; var gi_manualUpdateIntervalSec = gi_defaultManualUpdateIntervalSec;//※コンフィグで変更可能 //他のタブが強制リロードをしたら一定時間以内に強制リロードしない間隔時間(秒) const gi_defaultForceUpdateLockTimeSec = 60; var gi_forceUpdateLockTimeSec = gi_defaultForceUpdateLockTimeSec;//※システムコンフィグで変更可能 //マークする件数(最大100までにする事、ローカル保存データのキーを2桁[00〜99]にしているため) ※但し一度に読み込まれている件数は20前後なのでそれ以上はマークされない const gi_defaultReadArticles = 10; var gi_readArticles = gi_defaultReadArticles;//※システムコンフィグで変更可能 //検索ページの更新トリガ前に上部詰め処理のCSSを一旦無効にする(CSSによって上部余白を更に詰める追い込み処理が起因して更新されない場合の救済措置) const gi_defaultDispabeCssOnSearchUpdate = 0; var gi_disableCssOnSearchUpdate = gi_defaultDispabeCssOnSearchUpdate;//※システムコンフィグで設定可能 //検索ページの更新トリガ前に上部詰め処理のCSSを一旦無効にする時に従来のスクロール処理間ウェイト設定に加算するウェイト値(ミリ秒) const gi_defaultDisableCssSearchWaitMs = 100; var gi_disableCssSearchWaitMs = gi_defaultDisableCssSearchWaitMs;//※システムコンフィグで設定可能 //検索ページのタブタイトル表記を短縮する const gi_defaultSearchPageShortTitle = 1;//※システムコンフィグで変更可能 var gi_searchPageShortTitle = gi_defaultSearchPageShortTitle; //既読ポイント背景色パターン以降がある場合 パターン以降先頭要素で繰り返し=0, パターン全体を繰り返す=1 const DEF_READ_COLOR_CYCLEMODE = 1; var READ_COLOR_CYCLEMODE = DEF_READ_COLOR_CYCLEMODE;//※システムコンフィグで変更可能 //RTと引用RT非表示設定 制限無し=0, RT非表示=1, 引用RT非表示=2, RT/引用RT両方非表示=3 const gi_defaultNotDispRt = 0; var gi_notDispRt = gi_defaultNotDispRt;//※コンフィグで設定可能 const NOTRT_NAME = ["0:RT=ON/QUOTE=ON","1:RT=OFF/QUOTE=ON","2:RT=ON/QUOTE=OFF","3:RT=OFF/QUOTE=OFF"]; //ツイート下部のアイコン類非表示設定 const gi_defaultNotDispCommIcon = 0; var gi_notDispCommIcon = gi_defaultNotDispCommIcon;//※コンフィグで設定可能 //NGワードの有効 const gi_defaultEnableNGWord = 1; var gi_enableNGWord = gi_defaultEnableNGWord;//※コンフィグで設定可能 /************************************************************ 各種定数・グローバル変数定義 ************************************************************/ //モードのインデックス(配列タイプで定義している他の項目に影響するので変更禁止) const MODE_NULL = 0; const MODE_HOME = 1; const MODE_LIST = 2; const MODE_USER = 3; const MODE_NOTI = 4; const MODE_SEAR = 5; const MODE_MAX = 6;//enum値最大値+1 //種別プリフィクス用文字列(MODE_XXXXのインデックスでアクセスされる) const gstrA_modeNamePrifix = ["NULL","HOME","LIST","USER","NOTI","SEAR"]; //スクロールによってトリガするタイプのページでスクロールを戻すまでのウェイト時間(ms) ※0msで動くはずだがPCの処理能力によっては最大1000msくらいまで増やす const SCROLL_TYPE_TRIGGER_WAIT = 0; //スクロール位置をトップと判定する範囲 const SCROLL_LIMIT = 6.0; //リストページは一定以上スクロールするとヘッダ部非表示のCSSが起因してか、いつまでもDOM更新が止まらなくなるので閾値を設けてbodyタグに目印をつけてCSSを無効にする var LIST_PAGE_SCROLL_LIMIT = window.innerHeight; //分割スクロールする場合のウェイト時間 const gi_splitScrollIntervalMs = 1000; //スクロール処理中の排他フラグ var gf_scrollOperation = false; //初期化が必要=0, 初期化済み=1 var gi_initComplete = 0; //前回処理URL var gstr_lastURL = ""; //前回処理タブ幅 var gi_lastInnerWidth = 0; //前回処理タブ高さ var gi_lastInnerHeight = 0; //チェックボックスコントロールに一意のIDを振る var gi_recIdx = 0; //短周期処理で読み込まれた記事数のカウンタ var gi_articleRecv = 0; //更新間隔カウンタ var gi_updateCountMs = 0; //監視間隔タイマの間隔(ミリ秒) const gi_timerIntervalMs = 1000; //監視間隔タイマ内でカウントして長周期の処理をする var gi_longTimerCount10 = 0; var gi_longTimerCount60 = 0; const gi_maxLongTimerCount10 = 10; const gi_maxLongTimerCount60 = 6; //短周期タイマオブジェクト var gtmr_shortTimer = null; //短周期タイマ開始時間を保持 var gstr_lastShortStart = null; //短周期タイマ処理のワンショット実施フラグ(情報表示部の色替え用) var gf_oneShotShortTimer = false; //短周期処理のワンショット実行を時間差で行うタイマ配列(下の時間定義と配列数を揃える事) gi_shortTimerIdleDelayCount 設定値までしか使われない var gobjA_delayOneShotShortTimer = [null,null,null,null,null]; //短周期処理のワンショット実行を行う時間(秒)(上のタイマオブジェクト定義と配列数を揃える事) gi_shortTimerIdleDelayCount 設定値までしか使われない const giA_delayOneShotShortTimerSec = [1,2,3,5,10]; //自動更新が停止中 var gi_displayPaused = 0; //スクロール位置の前回値 var gf_lastYOffset = 0; //最後に更新をかけた時間 var gdt_lastTriggerTime = new Date(); //Home上部のエディット欄で編集をしていた時間 var gobj_editTime = new Date(); //編集をしていた時間からの経過時間(ms) この時間以内にツイートしましたダイアログを捕捉したらスクロールを戻す const EDIT_PAST_TIME = 10000; //初期処理を連続してリトライしている場合は再試行回数ぶん起動までの時間を延ばしてゆく var gi_clearElementErrorCount = 0; //gi_shortIntervalMsに乗算する上限値(250ms * 10 = 2.5sec) const MAX_RETRY_CLEAR_ELEMENT = 10; //スクロールによるトリガを行っているモード var gi_execTriggerByScroll = 0; //読込件数表示を消去するまでの時間(ms) const READ_COUNT_CLEARTIMEMS = 3000; //DOM更新イベントが正常に動作しているかどうかチェックする時間(ms) const CHECK_DOM_INTERVAL = 100; //DOM更新イベントの正常性チェックは起動直後のみ(DOMイベントを受信したらfalseに落とす) var gf_firstDOM = true; //DOM更新イベントが発生する変更をわざと加えてイベントがあがってくるかテストするモード=1 var gi_testEventMode = 0; //DOM更新から時間が経過したらobserverを張り直す(秒) const OBSERVER_REBUILDTIMESEC = 600; //更新を受信してから時間が経過していたらobserverを張り直す(秒) const OBSERVER_RECVPASTTIMESEC = 600; //情報表示部ボタンのHover中 var gi_onButtonHover = 0; //ヘルプ・コンフィグ系のダイアログ表示のテーブル幅・フォント倍率設定 const DIALOG_MIN_WIDTH = "390px"; const DIALOG_MAX_WIDTH = "500px"; const DIALOG_FONT_SIZE = "75%"; function getDialogWidth(){ var max = (DIALOG_MAX_WIDTH).replace("px","") - 44; var min = (DIALOG_MIN_WIDTH).replace("px","") - 44; return (window.innerWidth > max ) ? max : ((window.innerWidth < min ) ? min : (window.innerWidth * 0.9)); } //自動更新の情報表示エレメント var gelm_dispInfo = null; //ボタンコントロールのエレメント var gelm_allParent = null; var gelm_allParent2 = null; var gelm_allParent3 = null; var gelm_btnParent = null; var gelm_btnShort = null; var gelm_btnInterval = null; var gelm_btnAutoOff = null; var gelm_btnHelp = null; var gelm_btnEdit = null; var gelm_btnCount = null; var gelm_btnCount2 = null; var gelm_btnLeft = null; var gelm_btnMid = null; var gelm_btnRight = null; //更新情報の表示エレメント、定周期で再利用するオブジェクト変数のグローバル化 var gelm0 = null; var gelm1 = null; var gelm2 = null; var gelm3 = null; var gelm4 = null; var gelm5 = null; var gelm6 = null; var gelm7 = null; var gelm8 = null; var gelm9 = null; var gelmObserv = null; var gdt_temp = null; //通知ページの新着クリア待ち合わせタイマ var gtmr_waitClear = null; //新着積み上げ完了待ちの待ち合わせタイマ var gtmr_waitContinuous = null; //新着積み上げ開始からの処理タイムアウトタイマ var gtmr_timeoutContinuous = null; //リロード告知ダイアログオブジェクト var gobj_reloadDialog = null; //新着積み上げ更新ポップアップダイアログオブジェクト var gelm_fixedPopupContinuousStart = null; var gelm_fixedPopupContinuousMove = null; var gelm_fixedPopupContinuousReturn = null; var gelm_fixedPopupContinuousWaitStart = null; var gelm_fixedPopupContinuousWaitLoop = null; var gelm_fixedPopupContinuousFinish = null; var gelm_fixedPopupContinuousEnd = null; //既読マーク捜索ポップアップダイアログオブジェクト var gelm_fixedPopupFindInfo = null; var gelm_fixedPopupFindCount = null; var gelm_fixedPopupFindConfirm = null; var gelm_fixedPopupFindContinue = null; //通知新着クリアポップアップダイアログオブジェクト var gelm_fixedPopupClearNewTweet = null; //DM新着クリアポップアップダイアログオブジェクト var gelm_fixedPopupClearNewDM = null; //先頭にスクロールポップアップダイアログオブジェクト var gelm_fixedScrToTop = null; //スクロール先頭で既読マークポップアップダイアログオブジェクト var gelm_fixedScrTopMark = null; //強制リロード待ちポップアップダイアログオブジェクト var gelm_fixedReloadConfirm = null; //ヘルプツールチップポップアップダイアログオブジェクト var gelmA_fixedToolTips = []; //デバッグ用ダイアログオブジェクト var gelm_debugDialog = null; // ***** 新着積み上げ更新機能関連 ***** //遷移先にまだボタンコントロールが構築されていない場合にリトライする最大試行回数 const MAX_UPDATE_CONTINUOUS_RETURN_RETRY = 10; var gi_updateContinuousReturnRetry = 0; //新着積み上げモード var gi_continuousMode = 0; //新着積み上げと先頭でマークを併用する特殊モード var gi_contAfterTopMark = 0; //新着積み上げモードの処理フェイズ var gi_continuousPhase = 0; const CONT_IDLE = 0; const CONT_WAITING = 1; const CONT_START1 = 2; const CONT_START2 = 3; const CONT_RETURN = 4; const CONT_DOMWAIT = 5; const CONT_WAITCONT = 6; const CONT_FINISH = 7; const CONT_TIMEOUT = -1; const CONT_ABORT = -2; const CONT_RETRYERROR = -3; //積み上げ前に読み込まれているアーティクルPATH var gstrA_beforeContArticles = []; //積み上げ前に読み込まれているアーティクル座標 var giA_beforeContArticlesOffset = []; //積み上げ更新に相当するDOM更新があがってきたか var gf_continuousDOMWaiting = false; //待ち合わせ中にDOM更新イベントを受信した回数 var gi_DOMEventRecvCount = 0; //DOM更新イベント受信フラグ var gf_DOMEventRecv = false; //DOM更新によってレコードを読み込んだか var gf_newArticleRecv = false; //次のフェーズに進んだ時に前フェーズのポップアップを消すまでのタイムラグ(ms) const CLOSE_CONTINUOUS_DELAY = 1000; // ***** 既読マーク遡り検索機能関連 ***** //遡り捜索モード var gi_findMode = 0; //遡り捜索DIALOG_FONT_SIZEのタイムスタンプ無視モード var gi_findNoTimeStamp = 0; //見つけた既読マーク var giA_findMark = []; //既読マーク捜索処理 var gi_findReadPointCount = 0; //既読マークの捜索モードで1スクロール置きに挟むウェイト const gi_defaultFindModeIntervalMs = 100; var gi_findModeIntervalMs = gi_defaultFindModeIntervalMs;//※コンフィグで設定可能 //既読マーク遡り中に読み込まれたアーティクルのタイムスタンプ蓄積 var gstrA_findModeArticleTimeStamp = []; //既読マーク遡り中に読み込まれたアーティクル数の前回値 var gi_lastFindModeArticleRecs = 0; //既読マーク遡り中に前回と読み込まれたアーティクル数が変わっていなかった回数 var gi_lastFindModeArticleRecsSameCount = 0; //既読マーク遡り中に前回と読み込まれたアーティクル数が変わっていなかった回数の上限 const MAX_FINDMODEARTICLERECSSAMECOUNT = 50; //遡る上限の件数 const MAX_CONTINUE_ARTICLES = 1000; //有効な既読マーク数(この数未満では捜索を行わない) const ACTIVE_READ_COUNT = 4; //発見した既読マーク数の閾値(全部見つからない前提なので有効な既読マーク数マイナスこの値がヒットしたら捜索終了) const FIND_READ_COUNTSUB = 2; //有効な既読マーク数が一定以上あったら判定を緩くする const FIND_READ_THRETHOLD = 8; //有効な既読マーク数が一定以上あったら一定割合以上でヒットとする const FIND_READ_RATIO = 0.75; //遡って読み込んだアーティクルから先頭の何件を既読マークのタイムスタンプと比較するか const FIND_OLD_ARTICLE_COUNT = 20; // ***** 先頭でマーク機能関連 ***** //次回のスクロール先頭で既読マークするモード var gi_flgScrTopMarkMode = 0; //次回のスクロール先頭で既読マークするモードに入った時のURL var gstr_flgScrToTopURL = ""; //次回のスクロール先頭で既読マークするモード中に他の画面に遷移して戻ってきた初回の検出 var gf_flgScrTopMarkReturn = false; // ***** 通知ページの新着クリア機能関連 ***** //通知ページの新着表示消去モードフラグ var gf_flgClearNotification = false; //通知ページの新着表示が消えるまでのポップアップ最大時間(秒) const CLEAR_NEWNOTI_SEC = 180; //新着が消えるのを待ち合わせるカウンタ var gi_chkNotificationCount = 0; const gi_chkNotificationCountMax = 100; //コンフィグ・システムコンフィグ表示中のフラグ(強制リロードなどを抑止するため) var gb_enableSettingWindow = false; //システムコンフィグで変更保存された項目がある=true, 変更なし=false var gb_changedSetting = false; //表示中のページ種別 0:unknown, 1:Home, 2:List, 3:User, 4:Notification, 5:Search var gi_dispMode = 0; //遷移の判定を初期構築処理で行うための前回値、比較しているので初期値は変えておく var gi_lastDispMode = -1; //初期構築中にドキュメントが未構築な状態 var gf_documentError = false; //MutationObserverでDOM更新が上がってきた最終タイムスタンプ保持 var gdt_lastDomTime = new Date(); var gdt_lastRecvTime = new Date(); //メディアサイズ 0:非表示, 1:最小サムネイル, 2:通常のコンパクトサムネイル, 3:元のまま const gi_defaultMediaSize = 2; var gi_mediaSize = gi_defaultMediaSize;//※コンフィグで設定可能 const MEDIA_NONE = 0; const MEDIA_SMALL = 1; const MEDIA_NORMAL = 2; const MEDIA_LARGE = 3; const MEDIA_LINK = 4; const SIZE_NAME = ["0:非表示","1:縮小(小)","2:縮小(中)","3:元サイズ","4:リンク"]; /********************************************************************************** setAttribute/getAttribute 固有キー文字列定義 (カスタムCSSのセレクタで使用される) *********************************************************************************/ //このスクリプト固有のプリフィクス const gstr_scrModeAttrPfx = "PSEUDOTWEETDECK"; //このスクリプト固有のメディアサイズ記録用属性名 const gstr_scrMediaAttr = "PTD_MEDIA"; //このスクリプト固有のRT表示切り替え用属性名 const gstr_scrNotRtAttr = "PTD_NOTRT"; //このスクリプト固有の引用RT表示切り替え用属性名 const gstr_scrNotQuoteAttr = "PTD_NOTQUOTE"; //このスクリプト固有のツイート下部コマンドアイコン表示切り替え用属性名 const gstr_scrNotCommIconAttr = "PTD_NOTCOMMICON"; //このスクリプト固有のリストページスクロール状態で切り替え用属性名 const gstr_scrScrollList = "PTD_LIST_SCROLL"; //このスクリプト固有の一部環境で検索ページ上部の隙間を更に詰める処理が起因して更新があがってこない時の強引な解決策用属性名 const gstr_scrSearchUpdate = "PTD_SEARCH_UPD"; //スクリプト固有のモード記録用属性名 const gstr_scrTypeAttr = "PTD_TYPE"; //スクリプト固有の既読ポイント判定用チェックボックス属性名 const gstr_scrReadPointAttr = "PTD_READ"; //スクリプト固有の既読ポイント判定用チェックボックス格納親属性名 const gstr_scrReadPointParentAttr = "PTD_READ_PARENT"; //スクリプト固有のカラーモード判定用属性名 const gstr_scrLightColorAttr = "PTD_LIGHTCOLOR"; //新着表示部のイベントトラップ目印用属性名 const gstr_scrNewTweetAttr = "PTD_NEWTWEET"; // ******** 非表示にした項目の目印 ********* //重複するRT非表示時に追加しておく属性 const gstr_multipleArticleAttr = "PTD_MULTI_RT"; //スクリプト固有の固定ツイート判定用属性名 const gstr_scrFixedUserAttr = "PTD_FIXED"; //NGワードの判定済み const gstr_scrNGAttr = "PTD_NGWORD"; //ヘルプツールチップス用のボタンエレメントID(左クリック用と右クリック用なので+2ずつインデックスをずらす) const BTNID_SHORT = MAX_CON_BUTTON; const BTNID_INTVL = MAX_CON_BUTTON + 2; const BTNID_ATOFF = MAX_CON_BUTTON + 4; const BTNID_HELP = MAX_CON_BUTTON + 6; const BTNID_EDIT = MAX_CON_BUTTON + 8; //操作ボタンコントロールのID const PARENT_BLOCK = "PTD_PARENT_BLOCK"; const PARENT_BLOCK2 = "PTD_PARENT_BLOCK2"; const PARENT_BLOCK3 = "PTD_PARENT_BLOCK3"; const BUTTON_BLOCK = "PTD_BUTTON_BLOCK"; const INFO_BLOCK = "PTD_INFO_BLOCK" const HELP_BLOCK = "PTD_HELP_BLOCK" const SHORT_BLOCK = "PTD_SHORT_BLOCK"; const INTERVAL_BLOCK = "PTD_INTERVAL_BLOCK"; const AUTO_BLOCK = "PTD_AUTO_BLOCK"; const EDITBTN_BLOCK = "PTD_EDIT_BLOCK"; const COUNTBTN_BLOCK = "PTD_COUNT_BLOCK"; const COUNTBTN_BLOCK2 = "PTD_COUNT_BLOCK2"; const INFOLBTN_BLOCK = "PTD_INFO_LBTN_BLOCK"; const INFOMBTN_BLOCK = "PTD_INFO_MBTN_BLOCK"; const INFORBTN_BLOCK = "PTD_INFO_RBTN_BLOCK"; const gstrA_allButtons = [ PARENT_BLOCK, PARENT_BLOCK2, PARENT_BLOCK3, BUTTON_BLOCK, INFO_BLOCK, HELP_BLOCK, SHORT_BLOCK, INTERVAL_BLOCK, AUTO_BLOCK, EDITBTN_BLOCK, COUNTBTN_BLOCK, COUNTBTN_BLOCK2, INFOLBTN_BLOCK, INFOMBTN_BLOCK, INFORBTN_BLOCK, ]; //ポップアップ部コントロールのID const POPUP_BLOCK = "PTD_POPUP_BLOCK"; //ポップアップ終了時間要素 const POPUP_ENDTIME = "PTD_POPUP_ENDTIME_BLOCK"; //コンフィグ画面コントロールID const SETTING_BLOCK = "PTD_SETTING_CONIG_BLOCK"; //エディット部表示非表示切り替え時の追加要素 const EDITSW_BLOCK = "PTD_EDIT_SWITCH_BLOCK"; //タイムスタンプ部にチェックボックス追加済みを示す追加要素 const TIME_FIXED = "PTD_TIME_FIXED_BLOCK"; //引用RT先のタイムスタンプ置換済みを示す追加要素 const TIME_FIXED_SUB = "PTD_TIME_FIXED_SUB_BLOCK"; //画像リンク部のclickを乗っ取った状態の追加要素 const IMAGE_LINK = "PTD_IMAGE_LINK"; //DEBUG表示用のテキスト部要素 const ELM_DEBUG_TEXT = "PTD_DEBUG_TEXT"; //チェックボックスエレメントに追加するタイムスタンプの要素名 const CHK_TIMESTAMP = "PTD_CHK_TIMESTAMP"; //チェックされたアーティクルのタイムスタンプ var gstrA_readTimeStamp = []; //チェックされたアーティクルのURL var gstrA_readArticleURL = []; for( gi_defIdx=0; gi_defIdx < gi_readArticles; gi_defIdx++ ){ gstrA_readTimeStamp[gi_defIdx] = ""; gstrA_readArticleURL[gi_defIdx] = ""; } //チェックされたアーティクルの背景色モード ※非表示モードの時=-1 var gi_readCheckedColorMode = 0; //Home上部の新着表示件数 var gi_numberNewTweetCount = 0; //ボタンコントロールクリック時のタイムスタンプ var gobj_buttonClickTime = new Date(); //ボタンコントロールを排他する時間(ms) const BUTTON_LOCK_TIME = 250; //デバッグモードのローカルストレージ表示排他 var gf_lockDispLocalStorage = false; //ダイアログ表示の余白 const CRLF = "\r\n"; const CRLFSPC = "\r\n  "; const SPC = "
\r\n  "; const SPT = "  "; /************************************************************ 情報表示部関連定義 ************************************************************/ //表示部・ボタン類の色替え var gi_colorType = 0; const TYPE_UPDATE = 1; const TYPE_UPSOON = 2; const TYPE_ACTIVE = 3; const TYPE_PAUSED = 4; const TYPE_HOLDTM = 5; const TYPE_RELOAD = 6; //情報表示部の固定サイズ(フォントサイズを変更したらここも合わせて変更する) const DEF_DISPINFO_WIDTH = "120px"; var DISPINFO_WIDTH = DEF_DISPINFO_WIDTH;//※システムコンフィグで変更可能 const DEF_DISPINFO_HEIGHT = "20px"; var DISPINFO_HEIGHT = DEF_DISPINFO_HEIGHT;//※システムコンフィグで変更可能 //情報表示部のフォントサイズ unknown,home,list,user,notification,search const DEF_INFO_TEXT_FONT_SIZE = "12px";//※システムコンフィグで変更可能 var gstrA_titleSize = []; //更新時間変更ボタン・自動更新停止ボタンのフォントサイズ unknown,home,list,user,notification,search const DEF_INFO_BTN_FONT_SIZE = "14px";//※システムコンフィグで変更可能 var gstrA_buttonSize = []; //文字フォントとボタンフォントのテーブルを初期化 for( gi_defIdx=0; gi_defIdx < MODE_MAX; gi_defIdx++ ){ gstrA_titleSize[gi_defIdx] = DEF_INFO_TEXT_FONT_SIZE; gstrA_buttonSize[gi_defIdx] = DEF_INFO_BTN_FONT_SIZE; } //Home新着件数表示コントロール [999] の横幅 const COUNTBTN_WIDTH = "40px"; //ヘルプツールチップスのポップアップコントロールの高さ(px) ※ポップアップコントロールは下端からの相対座標なのでウィンドウ内部の高さからコントロールの高さを減算 const DEF_FLOAT_POPUP_HEIGHT = 300; var gi_floatPopupHeight = DEF_FLOAT_POPUP_HEIGHT; //ヘルプツールチップスのポップアップコントロールを表示するY軸方向のマージン(px) ※ポップアップコントロールを上部ヘッダ(スクロールしない固定部)ぶんずらす為の値 const DEF_FLOAT_POPUP_MARGIN = 45; var gi_floatPopupMargin = DEF_FLOAT_POPUP_MARGIN; //ホームTLの「フォロー中」表示を置き換える文字列(置き換えない場合は空文字 "" にしておく) const HOME_TL_NAME = "HomeTL"; //ボタンコントロールの文字列 var BTN_TXT_AUT = "◆";// 自動更新強制OFF切り替えボタン var BTN_TXT_SRT = "▲";// 短周期タイマのワンショット実行・動作切り替えボタン var BTN_TXT_INT = "■";// コンフィグ・システムコンフィグボタン var BTN_TXT_HLP = "?";// ヘルプダイアログ表示ボタン var BTN_TXT_ED1 = "↑";// エディット欄表示切り替えボタン:表示ON中 var BTN_TXT_ED0 = "↓";// エディット欄表示切り替えボタン:表示OFF中 var BTN_TXT_BTNL = "BTN1";// 情報表示部の左ボタン var BTN_TXT_BTNM = "BTN2";// 情報表示部の中ボタン var BTN_TXT_BTNR = "BTN3";// 情報表示部の右ボタン var BTN_TXT_BTNC = "BTN4";// 件数表示部のボタン //表示部固定文字列 const TXT_COUNTDOWNTIM = "[ #### / $$$$$$$$ ]";//自動更新有効時のカウントダウン表示 const TXT_NOCOUNTDOWNT = "[ Active/ $$$$$$$$ ]";//自動更新有効時のカウントダウン表示なし設定時 const TXT_PAUSEDUPDATE = "[ Paused Refresh...]";//自動更新停止中 const TXT_LATESTNOFOCS = "[ Auto / $$$$$$$$ ]";//自動更新有効時フォーカスのない時の表示 const TXT_PAUSEDUPDAT2 = "[ Paused/ $$$$$$$$ ]";//自動更新停止中(最終更新時間表示あり) const TXT_MANUALUPDATE = "[ Manually Update. ]";//手動更新実施中 const TXT_AUTOCLICKMOR = "[ AutoClick Update ]";//さらに表示の自動クリック更新実施中 const TXT_RELOADEXTEND = "[ Reload Extended. ]";//強制リロード時間延長 const TXT_FORCERELOADD = "[ Force ReloadPage ]";//強制リロード実施中 const TXT_CHANGEBGTYPE = "[ Change BG Type# ]";//既読マーク背景パターン変更 const TXT_CHANGEBGNONE = "[ ReadMarkDisabled ]";//既読マーク無効 const TXT_CLEARNEWNOTI = "[ Clear New Info...]";//通知ページの新着表示クリア中 /************************************************************ 汎用関数定義 ************************************************************/ //本スクリプトとは無関係のURLかどうかを判定 ※先にPATH_LISTかどうかを判定しないとリスト一覧の i なし lists にパターンマッチしてしまうので注意 function isOtherURL(hr){ //hr: URL/Path //return: true=無関係のURL / false=スクリプト処理対象のURL if( hr.indexOf(TWITTER_URL + "messages") != -1 || hr.indexOf(TWITTER_URL + "compose") != -1 || hr.indexOf(TWITTER_URL + "settings") != -1 || hr.indexOf(TWITTER_URL + "explore") != -1 || hr.indexOf(TWITTER_URL + "i/bookmarks") != -1 || hr.indexOf(TWITTER_URL + "i/circles") != -1 || hr.indexOf(TWITTER_URL + "i/connect_people") != -1 || hr.indexOf(TWITTER_URL + "i/display") != -1 || hr.indexOf(TWITTER_URL + "intent/") != -1 || hr.indexOf(TWITTER_URL + "ja/") != -1 || hr.indexOf(TWITTER_URL + "en/") != -1 || (hr.indexOf(TWITTER_URL) != -1 && hr.indexOf("/status/") != -1) || (hr.indexOf(TWITTER_URL) != -1 && hr.indexOf("/lists") != -1)){ return true; } return false; } //日付時刻の整形 function toFormatedDateString(date){ //date: 日時オブジェクト //return: 整形後の日付時刻 // yy/mm/dd HH:MM:SS var ret = ("0" + date.getFullYear()).slice(-2) + "/" + ("0" + (date.getMonth() + 1)).slice(-2) + "/" + ("0" + date.getDate()).slice(-2) + " " + ("0" + date.getHours()).slice(-2) + ":" + ("0" + date.getMinutes()).slice(-2) + ":" + ("0" + date.getSeconds()).slice(-2); return ret; } //時刻の整形 function toFormatedTimeString(date){ //date: 日時オブジェクト //return: 整形後の時刻 // HH:MM:SS var ret = ("0" + date.getHours()).slice(-2) + ":" + ("0" + date.getMinutes()).slice(-2) + ":" + ("0" + date.getSeconds()).slice(-2); return ret; } //カラーコード変換 "#ffffff" → "rgb(255,255,255)" function convHEXtoRGB(colorCodeHex){ return "rgb(" + String(colorCodeHex.slice(1).match(/.{2}/g).map(function(hex){return parseInt(hex,16);})) + ")"; } //カラーコード変換 "rgb(255, 0, 255)" → "#ff00ff" function convRGBtoHEX(colorCodeRgb){ return "#" + colorCodeRgb.match(/\d+/g).map(function(rgb){return ("0" + parseInt(rgb).toString(16)).slice(-2);}).join(""); } //配列の昇順クイックソート function quicksort(ary) { //ary: ソート対象配列 function impl(start, end){ if (start + 1 >= end) return; let [pivot, l, r] = [start, start, end - 1]; while (l < r) { while (ary[pivot] < ary[r]) r--; while (ary[l] <= ary[pivot] && l < r) l++; [ary[l], ary[r]] = [ary[r], ary[l]]; } [ary[pivot], ary[l]] = [ary[l], ary[pivot]]; impl(start, l); impl(l+1, end); } impl(0, ary.length); } //親エレメントを取得する function getParentElement( obj, depth ){ //obj: 対象オブジェクト //depth: 何階層上の親を求めるか //return: 親オブジェクト 無効の場合=null var ret = obj; for( var i=0; i 0 ){ e[0].style.overflowY = "hidden"; } } //親要素にマウスホイールを処理させないのを解除 function releaseWheelEvents(){ var e = document.querySelectorAll('html'); if( e.length > 0 ){ e[0].style.overflowY = "scroll"; } } //イベント処理を行わないエレメント設定 function setStopEvents(obj,lc=true,rc=false){ //obj: 対象エレメントオブジェクト //lc: 左クリック抑止=true //rc: 右クリック抑止=true if( lc ) obj.onclick = funcStopEvent; if( rc ) obj.oncontextmenu = funcStopEvent; obj.onkeydown = funcStopEvent; obj.onkeyup = funcStopEvent; obj.onkeypress = funcStopEvent; obj.onchange = funcStopEvent; } //表示中タブのURL(共通部以降のPATH)を取得 function getPageURL(){ //return: URL文字列, 無効時="" var u = window.location.href + ""; if( u.length < (TWITTER_URL.length + 4) ) return ""; u = u.replace(TWITTER_URL, ""); u = decodeURIComponent(u); getModeFromURL(); if( gi_dispMode == MODE_NULL ) return ""; return u; } /************************************************************ イベント処理関連関数 ************************************************************/ //要素の初回書き換わりを監視 window.addEventListener('load', function(){ dispDebugTextWithTime("window.load : Window loaded", LOG_SYS); //起動直後とりあえず非表示にしておく gelm0 = document.querySelectorAll('body'); if( gelm0.length > 0 ){ gelm0[0].setAttribute( gstr_scrMediaAttr, 0 ); }else{ window.reload(); return; } //リサイズされた時に情報表示部+ボタンが消失するパターンの救済 window.addEventListener("resize", function(){ dispDebugTextWithTime("window.resize : (" + Math.floor(window.innerHeight) + " x " + Math.floor(window.innerWidth) + ")", LOG_SYS); //初回または初期処理が終わったあとにリサイズイベントが遅れてきた場合は処理しない if( gi_lastInnerWidth == 0 || gi_lastInnerWidth == Math.floor(window.innerWidth) || gi_lastInnerHeight == 0 || gi_lastInnerHeight == Math.floor(window.innerHeight) ) return; //各種カウンタの初期化 dispDebugTextWithTime("window.resize : Retry clearElements()", LOG_SYS); resetElements(); //デバッグウィンドウが出ていたら再構築 if( gelm_debugDialog !== null ){ closePopupMessage(gelm_debugDialog); debugFunction(); } }); document.addEventListener("visibilitychange", function(){ dispDebugTextWithTime("document.visibilitychange : visibilityState=" + document.visibilityState + ", hasFocus=" + document.hasFocus(), LOG_SYS); }); window.addEventListener("focus", function(){ dispDebugTextWithTime("window.focus : visibilityState=" + document.visibilityState + ", hasFocus=" + document.hasFocus(), LOG_SYS); }); window.addEventListener("blur", function(){ dispDebugTextWithTime("window.blur : visibilityState=" + document.visibilityState + ", hasFocus=" + document.hasFocus(), LOG_SYS); }); window.addEventListener("pageshow", function(){ dispDebugTextWithTime("window.pageshow : visibilityState=" + document.visibilityState + ", hasFocus=" + document.hasFocus(), LOG_SYS); }); window.addEventListener("pagehide", function(){ dispDebugTextWithTime("window.pagehide : visibilityState=" + document.visibilityState + ", hasFocus=" + document.hasFocus(), LOG_SYS); }); document.addEventListener("freeze", function(){ dispDebugTextWithTime("document.freeze : visibilityState=" + document.visibilityState + ", hasFocus=" + document.hasFocus(), LOG_SYS); }); document.addEventListener("resume", function(){ dispDebugTextWithTime("document.resume : visibilityState=" + document.visibilityState + ", hasFocus=" + document.hasFocus(), LOG_SYS); }); window.navigator.connection.addEventListener("change", function(){ dispDebugTextWithTime("connection.change : downlink=" + window.navigator.connection.downlink, LOG_SYS); }); window.addEventListener('online', function(){ dispDebugTextWithTime("window.online : onLine=" + window.navigator.onLine, LOG_SYS); }); window.addEventListener('offline', function(){ dispDebugTextWithTime("window.offline : onLine=" + window.navigator.onLine, LOG_SYS); saveDebugData(); }); //キーイベント gelm0[0].addEventListener("keydown", funcKeyEvent); //スクロール位置監視のイベントリスナーを開始する window.addEventListener('scroll', funcScrollEvent); //メイン処理開始 initMain(); //console.log("★load: WindowLoaded"); }); //再構築 function resetElements(lastMode=null){ //lastMode: gi_lastDispModeを変更する場合に設定 dispDebugTextWithTime("resetElements : lastMode=" + lastMode); gi_updateCountMs = 0; gi_displayPaused = 0; gi_initComplete = 0; if( lastMode !== null ){ gi_lastDispMode = lastMode; } clearElements(); } //アーティクル数に応じた可変要素の1つ上のエレメントをDOM更新監視(アーティクルの増減をイベントとして受け取る) var observer = new MutationObserver(function(){ //DOMの変化が起こった時の処理 gdt_lastDomTime = new Date(); gf_firstDOM = false; if( gi_testEventMode != 1 || gi_continuousMode || gf_continuousDOMWaiting || gi_findMode ){ //console.log("★DOMが変化しました " + toFormatedTimeString(gdt_lastDomTime) ); dispDebugTextWithTime("MutationObserver : DOM Changed", LOG_DOM); //短周期タイマ再開 restartShortTimerInterval(); }else{ dispDebugTextWithTime("MutationObserver : DOM Test OK", LOG_TRC); gi_testEventMode = 0; return; } if( gi_continuousMode && gf_continuousDOMWaiting && gi_continuousPhase > 0 ){ gf_DOMEventRecv = true;; //時間切れのタイマを解除 if( gtmr_timeoutContinuous !== null ){ window.clearTimeout(gtmr_timeoutContinuous); gtmr_timeoutContinuous = null; } if( gi_continuousPhase != CONT_FINISH ){ //DOM受信から経過時間を計るタイマの開始・延長 if( gtmr_waitContinuous !== null ){ //既にタイマが張られていたら解除して再度タイマ開始 window.clearTimeout(gtmr_waitContinuous); gtmr_waitContinuous = window.setTimeout(clickNewestTweetWaiting, gi_updateContinuousResultTimeMs * gi_updateContinuousDOMPastCycle); dispDebugTextWithTime("MutationObserver : Waiting Timer Reset", LOG_DOM); }else{ //初回のタイマ開始 gtmr_waitContinuous = window.setTimeout(clickNewestTweetWaiting, gi_updateContinuousResultTimeMs * gi_updateContinuousDOMPastCycle); dispDebugTextWithTime("MutationObserver : Waiting Timer Start", LOG_DOM); if( gi_updateContinuousDispPopup ){ window.setTimeout( closePopupContinuousReturn, CLOSE_CONTINUOUS_DELAY ); closePopupContinuousWaitStart(); gelm_fixedPopupContinuousWaitStart = dispPopupMessage("新着積み上げ更新の完了待ち開始", -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT); } } }else{ if( gtmr_waitContinuous !== null ){ window.clearTimeout(gtmr_waitContinuous); } } } }); //停止していた短周期タイマを再開させる function restartShortTimerInterval(){ if( gi_idleShortTimer ){ if( gtmr_shortTimer === null ){ gtmr_shortTimer = window.setInterval(replaceElements, gi_shortIntervalMs); dispDebugTextWithTime("restartShortTimerInterval : Restart", LOG_SHRT); for( var i=0; i giA_delayOneShotShortTimerSec[i] * 1000 ){ gobjA_delayOneShotShortTimer[i] = window.setTimeout( function(i, withTrigger, objTimer){ if( objTimer !== null ) return; replaceElementsOneShot(); var txt = (withTrigger)?"After execTrigger":"After stopTimer"; dispDebugTextWithTime( txt + " OneShot[" + i + "]=" + ("00" + giA_delayOneShotShortTimerSec[i]).slice(-2) + "s", LOG_SHRT); gobjA_delayOneShotShortTimer[i] = null }, giA_delayOneShotShortTimerSec[i] * 1000, i, withTrigger, gtmr_shortTimer ); } } } //監視するエレメントの取得・再取得 async function clearElements(resetMode=false){ //resetMode: Observerのみ再設定する=true if( gi_initComplete == 1 && resetMode == false ){ dispDebugTextWithTime("clearElements : initComplete = 1 Skip resetMode=[" + resetMode + "]"); return; } //スクリプト固有の属性を一旦削除 gelm0 = document.querySelectorAll('body[' + gstr_scrTypeAttr +']'); if( gelm0.length > 0 ){ gelm0[0].removeAttribute( gstr_scrTypeAttr ); } gelm0 = document.querySelectorAll('body[' + gstr_scrLightColorAttr +']'); if( gelm0.length > 0 ){ gelm0[0].removeAttribute( gstr_scrLightColorAttr ); } //URLからモードを決定 gi_lastDispMode = gi_dispMode; getModeFromURL(); if( gi_lastDispMode != gi_dispMode ){ //遷移後初回だけ dispDebugTextWithTime("clearElements : gi_dispMode = " + gstrA_modeNamePrifix[gi_dispMode], LOG_SYS); } if( gi_dispMode == MODE_NULL ){ if( ++gi_clearElementErrorCount > MAX_RETRY_CLEAR_ELEMENT ) gi_clearElementErrorCount = MAX_RETRY_CLEAR_ELEMENT; window.setTimeout(clearElements, gi_shortIntervalMs * gi_clearElementErrorCount); if( gi_lastDispMode != gi_dispMode ){ //遷移後初回だけ dispDebugTextWithTime("clearElements : MODE_NULL Retry", LOG_SYS); } return; } if( resetMode === null ){ //各種カウンタの初期化 gi_updateCountMs = Math.trunc(Math.random() * giA_updateIntervalMs[gi_dispMode] / 1000) * 1000; gi_displayPaused = 0; gelm0 = gelm1 = gelm2 = gelm3 = gelm4 = gelm5 = gelm6 = gelm7 = gelm8 = gelm9 = null; } gelmObserv = null; //監視対象の要素オブジェクト if( gi_dispMode == MODE_HOME ){ gelm1 = document.querySelectorAll('div[aria-label="タイムライン: ホームタイムライン"]'); }else if( gi_dispMode == MODE_LIST ){ gelm1 = document.querySelectorAll('div[aria-label="タイムライン: リスト"]'); LIST_PAGE_SCROLL_LIMIT = window.innerHeight; }else if( gi_dispMode == MODE_USER ){ gelm1 = document.querySelectorAll('div[aria-label^="タイムライン: "][aria-label$="さんのポスト"]'); }else if( gi_dispMode == MODE_NOTI ){ gelm1 = document.querySelectorAll('div[aria-label="タイムライン: 通知"]'); }else if( gi_dispMode == MODE_SEAR ){ gelm1 = document.querySelectorAll('div[aria-label="タイムライン: タイムラインを検索"]'); } if( gelm1.length > 0 ) gelmObserv = gelm1[0].firstElementChild; if( gelmObserv === null ){ //ドキュメント未構成のため時間を置いてリトライ if( ++gi_clearElementErrorCount > MAX_RETRY_CLEAR_ELEMENT ) gi_clearElementErrorCount = MAX_RETRY_CLEAR_ELEMENT; window.setTimeout(clearElements, gi_shortIntervalMs * gi_clearElementErrorCount); //連続して出ないように初回だけ表示 if( ! gf_documentError ){ dispDebugTextWithTime("clearElements : Document not found [forDOM]", LOG_SYS); } gf_documentError = true; return; } gf_documentError = false; //カスタムCSSで判別するための要素を追加(ユーザーページは消去法で判定しないと無理で、カスタムCSSではそんな判別は出来ないため) gelm0 = document.querySelectorAll('body'); if( gelm0.length > 0 ){ gelm0[0].setAttribute( gstr_scrTypeAttr, gstr_scrModeAttrPfx + gstrA_modeNamePrifix[gi_dispMode] ); //ライトカラー設定の時に目印 if( ! COLOR_MODE ){ gelm0[0].setAttribute( gstr_scrLightColorAttr, "" ); } //URL別の設定を読み込む loadPageSettings(); //既読ポイント背景色設定の読込 if( gi_enableReadPointCheckBox ){ loadReadPointColorSetting(); } }else{ dispDebugTextWithTime("clearElements : Document not found [body]", LOG_ERR); return; } var i; //固定ツイートを非表示にするための目印追加 if( gi_dispMode == MODE_USER ){ gelm2 = gelmObserv.firstElementChild; if( gelm2 !== null ){ gelm3 = gelm2.querySelectorAll('span'); for( i=0; i < gelm3.length; i++ ){ if( gelm3[i].textContent == "固定" ){ gelm2.setAttribute(gstr_scrFixedUserAttr,"true"); gelm4 = gelm2.firstElementChild; break; } } } } const TIMELINE_UP_TAB = 'div[aria-label="ホームタイムライン"] div[role="tablist"][data-testid="ScrollSnap-List"] div[role="presentation"]:has(a[role="tab"])'; //Homeページで「おすすめ」を非表示にしていた場合に「フォロー中(HomeTL)」にフォーカスを移す (style.displayでは状態が獲得出来ないのでclientHeigtを見るべし) if( gi_dispMode == MODE_HOME ){ gelm3 = document.querySelectorAll( TIMELINE_UP_TAB ); if( gelm3.length > 1 ){ gelm4 = gelm3[0].querySelectorAll('a[role="tab"]'); gelm5 = gelm3[1].querySelectorAll('a[role="tab"]'); if( gelm4.length > 0 && gelm5.length > 0 ){ if( gelm4[0].clientHeight == 0 && gelm4[0].getAttribute("aria-selected") == "true" ){ gelm5[0].click(); //console.log("★clearElements : HOME おすすめ→フォロー中にフォーカス変更"); } } } } //検索ページで「話題のツイート」を非表示にしていた場合に「最新」にフォーカスを移す (style.displayでは状態が獲得出来ないのでclientHeigtを見るべし) if( gi_dispMode == MODE_SEAR ){ gelm3 = document.querySelectorAll( TIMELINE_UP_TAB ); if( gelm3.length > 1 ){ gelm4 = gelm3[0].querySelectorAll('a[role="tab"]'); gelm5 = gelm3[1].querySelectorAll('a[role="tab"]'); if( gelm4.length > 0 && gelm5.length > 0 ){ if( gelm4[0].clientHeight == 0 && gelm4[0].getAttribute("aria-selected") == "true" ){ gelm5[0].click(); //console.log("★clearElements : SEARCH 話題→最新にフォーカス変更"); } } } } //MutationObserver監視時のオプション const configObserver = { attributes: false, characterData: true, childList: true, subtree: false, attributeOldValue: false, characterDataOldValue: false }; //既に張られているovserverを消去 observer.disconnect(); //要素の変化監視をスタート observer.observe(gelmObserv, configObserver); gdt_lastDomTime = new Date(); gf_firstDOM = true; //起動時のドキュメント構築中の親エレメントが操作されてしまうとObserverが無効になるケースがあるのでイベントが上がるか要素追加してみる gi_testEventMode = 1; var dmy = document.createElement('DIV'); dmy.textContent = "[PseudoTweetDeck] Script Loading..."; gelmObserv.appendChild(dmy); gelmObserv.removeChild(dmy); window.setTimeout(checkDOMEvent, CHECK_DOM_INTERVAL); dispDebugTextWithTime("clearElements : checkDOMEvent()", LOG_DOM); //表示更新用エレメントの再取得 gelm_dispInfo = null; gi_initComplete = 1; gstr_lastURL = window.location.href; gi_lastInnerWidth = Math.floor(window.innerWidth); gi_lastInnerHeight = Math.floor(window.innerHeight); //console.log("★clear: Element"); dispDebugTextWithTime("clearElements : Init complete Reset=" + ((resetMode===null)?"false":"true") + " / Mode=" + gstrA_modeNamePrifix[gi_dispMode] ); //短周期タイマ再開 restartShortTimerInterval(); gi_clearElementErrorCount = 0; } //ボタンコントロールを作り直す function rebuildInfoButtons(){ getModeFromURL(); var e = document.getElementById(PARENT_BLOCK); if( e === null ){ if( gi_dispMode != MODE_NULL ){ dispDebugTextWithTime("rebuildInfoButtons : resetElements()", LOG_WARN); resetElements(-1); } } } //observerを設定したあとにDOMイベントが上がってきているかチェック function checkDOMEvent(){ if( gf_firstDOM ){ dispDebugTextWithTime("checkDOMEvent : Init retry", LOG_WARN); gi_lastDispMode = -1; gi_initComplete = 0; clearElements(); } } //新着表示部のクリックイベントで更新表示と時間記録を行う function onClickNewTweet(){ if( gi_modeAutoOff ){ //色替え・手動更新表示 forceUpdateColor(COLOR_UPDATE, TXT_MANUALUPDATE); }else{ //色替え・自動クリック更新表示 forceUpdateColor(COLOR_UPDATE, TXT_AUTOCLICKMOR); } //更新トリガの時間を記録 gdt_lastTriggerTime = new Date(); //手動でトリガを掛けたので更新カウンタ時間を満了時間にする gi_updateCountMs = giA_updateIntervalMs[gi_dispMode] - 1000; } //キーイベントの処理 function funcKeyEvent(e){ //e: イベントオブジェクト //return: true親フォームにイベントを伝える false:伝えない if( ! gi_disableKeyEvent ) return true; var role = document.activeElement.getAttribute("role"); var find = false; var isEdit = (role == "textbox" || role == "combobox" ) ? true : false; //編集中 if( isEdit ){ //console.log("funcKeyEvent : EditActive KeyCode=" + e.keyCode); return true; } //単独キー if( ! e.ctrlKey && ! e.shiftKey && ! e.altKey ) { switch (e.keyCode){ case 74: // 'J' case 75: // 'K' case 71: // 'G' case 78: // 'N' case 77: // 'M' case 191: // '/' case 76: // 'L' case 82: // 'R' case 84: // 'T' case 83: // 'S' case 66: // 'B' case 85: // 'U' case 88: // 'X' case 79: // 'O' case 73: // 'I' find = true; break; } } //Shift+キー if( ! e.ctrlKey && e.shiftKey && ! e.altKey ) { switch (e.keyCode){ case 191: // '?' find = true; break; } } if( find ){ e.stopImmediatePropagation(); e.preventDefault(); console.log("funcKeyEvent : StopEvent KeyCode=" + e.keyCode); return false; } return true; } /************************************************************ 更新・表示関連関数 ************************************************************/ //毎秒の定周期更新処理メイン function updateTimeline() { //メイン処理で使い回す現在時間を取得 gdt_temp = new Date(); //画面遷移を判定し、変わっていたら初期処理をやりなおす if( isChangedDisp() ) return; //長周期タイマ処理 execLongSpanTimer(); //読込件数表示をしていたら経過時間で消去 clearNewTweetCount(); //ツイート完了の純正ポップアップを捕捉してスクロール戻しとエディット非表示を行う if( gi_dispMode == MODE_HOME && gi_newTweetCompleteCloseEdit ){ checkNewTweetComplete(); } //自動更新に該当しないページは何もせず戻る if( gi_dispMode == MODE_NULL ) return; //短周期タイマ開始から時間が経過したらタイマを停止させる checkStopShortTimer(); //コンフィグ表示中は処理せず戻る if( gb_enableSettingWindow ) return; //カウントダウン処理メイン execCountDownMain(); //更新に関する情報を表示する updateDisplayInfo(); } //短周期タイマ開始から時間が経過したらタイマを停止させる function checkStopShortTimer(){ if(gi_idleShortTimer){ //短周期タイマ開始から時間が経過したらタイマを停止させる if( gtmr_shortTimer !== null ){ if( gdt_temp.getTime() - gstr_lastShortStart.getTime() > gi_shortTimerIdleMs ){ window.clearInterval(gtmr_shortTimer); gtmr_shortTimer = null; gstr_lastShortStart = gdt_temp; dispDebugTextWithTime("checkStopShortTimer : Stop short timer", LOG_SHRT); //console.log("★gtmr_shortTimer: ShortTimerOFF [" + toFormatedDateString(gdt_temp) + "]"); //短周期タイマを停止させたあと時差でワンショット実行する execDelayOneShotShortTimer(false); } }else{ //停止していた短周期タイマをワンショット実行 var tmp = document.title; if( tmp.indexOf("@") == 0 || tmp.slice(-3) == "\/ X" ){ dispDebugTextWithTime("checkStopShortTimer : Title changed OneShot", LOG_SHRT); replaceElementsOneShot(); } } } } //画面遷移を判定 function isChangedDisp(){ //return: 初期処理が必要=true, 通常=false if( gstr_lastURL != window.location.href ){ dispDebugTextWithTime("isChangedDisp : [" + decodeURIComponent((gstr_lastURL + "").replace(TWITTER_URL,'')).substr(0,25) + "]→[" + decodeURIComponent((window.location.href + "").replace(TWITTER_URL,'')).substr(0,25) + "]", LOG_SYS ); gstr_lastURL = window.location.href; getModeFromURL(); var u = getPageURL(); gelm0 = document.querySelectorAll('body'); if( gelm0.length > 0 ){ //遷移したらメディアサイズ情報を初期化しておく if( gi_dispMode == MODE_NULL ){ gelm0[0].removeAttribute( gstr_scrTypeAttr ); gelm0[0].setAttribute( gstr_scrMediaAttr, 3 ); }else{ //メディアサイズ設定を読み込む gi_mediaSize = gi_defaultMediaSize; var v = loadSetting( MEDIA_HEADER, u ); if( v !== null ){ v = Number(v); gi_mediaSize = v; } gelm0[0].setAttribute( gstr_scrMediaAttr, v ); } } //初期処理 gi_initComplete = 0; window.setTimeout( clearElements, 0 ); return true; } return false; } //読込件数表示をしていたら経過時間で消去 function clearNewTweetCount(){ if( gelm_btnCount !== null && gi_countPosition > BTN4_POSITION_NONE && (gelm_btnCount.textContent + "").indexOf("(") == 0 ){ if(gdt_temp.getTime() - gdt_lastRecvTime.getTime() > READ_COUNT_CLEARTIMEMS ){ gelm_btnCount.textContent = ""; } } } const EDIT_CONTROL_BLOCK = 'div[class="css-175oi2r r-kemksi r-1h8ys4a"] div[aria-label="ポスト本文"] span[data-text="true"]'; //更新が必要かどうかをURLとフォーカスコントロールの状態などから判定(内部の画面遷移とlocation.hrefは一致しないタイミングがあるので更新直前に確認が必要) function isShouldNotUpdate(){ //return: true=更新しない状態 / false=更新する状態 //HOME if( gi_dispMode == MODE_HOME ){ if(window.location.href == TWITTER_URL + PATH_HOME ){ if( isHomeEditControlActive() ) return true; if( gi_modeAutoOff == 1 ){ return true; }else{ return false; } }else{ return true; } //console.log("※Current href + [" + window.location.href + "] / Focus tagName + [" + focusElement.tagName + "] return true"); return true; } //LIST if( gi_dispMode == MODE_LIST ){ if(window.location.href.indexOf(TWITTER_URL + PATH_LIST) != -1 ){ //console.log("※Current href + [" + window.location.href + "] / Focus tagName + [" + focusElement.tagName + "] return false"); if( gi_modeAutoOff == 1 ){ return true; }else{ return false; } } //console.log("※Current href + [" + window.location.href + "] / Focus tagName + [" + focusElement.tagName + "] return true"); return false; } //USER if( gi_dispMode == MODE_USER ){ var hr = window.location.href; if(hr == (TWITTER_URL + PATH_HOME) || hr.indexOf(TWITTER_URL + PATH_LIST) != -1 || hr.indexOf(TWITTER_URL + PATH_NOTI) != -1 || hr.indexOf(TWITTER_URL + PATH_SEAR) != -1 || isOtherURL(hr) ){ //console.log("※Current href + [" + window.location.href + "] / Focus tagName + [" + focusElement.tagName + "] return false"); return true; } //console.log("※Current href + [" + window.location.href + "] / Focus tagName + [" + focusElement.tagName + "] return true"); if( gi_modeAutoOff == 1 ){ return true; }else{ return false; } } //NOTI if( gi_dispMode == MODE_NOTI ){ if(window.location.href.indexOf(TWITTER_URL + PATH_NOTI) != -1 ){ //console.log("※Current href + [" + window.location.href + "] / Focus tagName + [" + focusElement.tagName + "] return false"); return false; } //console.log("※Current href + [" + window.location.href + "] / Focus tagName + [" + focusElement.tagName + "] return true"); return true; } //SEAR if( gi_dispMode == MODE_SEAR ){ var focusElement = document.activeElement; var focusAttr = focusElement.getAttribute("data-testid"); if(focusAttr !== null){ //検索ボックスにフォーカスがあったら更新させない if(focusAttr == "SearchBox_Search_Input"){ //console.log("※InputBox Enable + [" + focusAttr + "] return true"); return true; }else{ //console.log("※Focus Attr + [" + focusAttr + "]"); } } if(window.location.href.indexOf(TWITTER_URL + PATH_SEAR) != -1 ){ //console.log("※Current href + [" + window.location.href + "] / Focus tagName + [" + focusElement.tagName + "] return false"); if( gi_modeAutoOff == 1 ){ return true; }else{ return false; } } //console.log("※Current href + [" + window.location.href + "] / Focus tagName + [" + focusElement.tagName + "] return true"); return true; } return true; } //毎秒処理のカウントダウン function execCountDownMain(){ //console.log("☆PageY-Offset=" + window.pageYOffset); if(window.pageYOffset <= SCROLL_LIMIT ) { if( ! isShouldNotUpdate() ){ if(gi_updateCountMs >= giA_updateIntervalMs[gi_dispMode]) { //フォーカス判定が外れた状態からの復帰 if( gi_initComplete == 0 ){ dispDebugTextWithTime("execCountDownMain : initComplete = 0" ); clearElements(); } if(giA_reloadTimeoutSec[gi_dispMode]){ //一定時間以上レコード更新が無い場合はリロードする if( ( gdt_temp.getTime() - gdt_lastRecvTime.getTime() ) > (giA_reloadTimeoutSec[gi_dispMode] * 1000) ){ var f = false; var v = "20" + loadSetting(FORCEUPDATE_HEADER, KEY_SYSTEM); if( v != null ){ var timeSub = (gdt_temp.getTime() - (new Date(v)).getTime() ); //短時間に実施しないため前回実施時刻を獲得 if( timeSub > (gi_forceUpdateLockTimeSec * 1000) ){ f = true; }else{ gi_updateCountMs = Math.trunc(Math.random() * giA_updateIntervalMs[gi_dispMode] / 1000) * 1000; forceUpdateColor(COLOR_RELOAD, TXT_RELOADEXTEND); dispDebugTextWithTime("execCountDownMain : Reload extend"); return; } }else{ f = true; } if( f ){ saveSetting(FORCEUPDATE_HEADER, KEY_SYSTEM, ( toFormatedDateString(gdt_temp)) ); closePopupReloadConfirm(); dispDebugTextWithTime("execCountDownMain : Reload confirm"); gelm_fixedReloadConfirm = popupConfirm( "リロードします", "キャンセル", function(){ window.clearTimeout(gobj_reloadDialog); gobj_reloadDialog = null; gdt_lastRecvTime = gdt_lastTriggerTime = gdt_temp; gi_updateCountMs = giA_updateIntervalMs[gi_dispMode] - 1000; closePopupReloadConfirm(); dispPopupMessage("強制リロードをキャンセルしました", gi_displayPopupCloseTimeSec); } ); gobj_reloadDialog = window.setTimeout( function(){ window.location.reload(); }, gi_reloadWaitMs ); gi_displayPaused = 0; gi_updateCountMs = 0; forceUpdateColor(COLOR_UPDATE, TXT_FORCERELOADD); gi_initComplete = 0; return; } } } //更新トリガ(通知ページの新着クリアは経過時間に関係なくトリガする) if( (gdt_temp.getTime() - gdt_lastTriggerTime.getTime() > gi_manualUpdateIntervalSec * 1000) || (gi_dispMode == MODE_NOTI) ){ execTrigger(true, null); dispDebugTextWithTime("execCountDownMain : Auto execTrigger()"); } //更新されたのでカウンタをリセット gi_displayPaused = 0; gi_updateCountMs = 0; //console.log("☆Counter Update0 [" + gi_updateCountMs + "]" ); }else{ //更新待ちカウンタの加算 gi_displayPaused = 0; gi_updateCountMs += gi_timerIntervalMs; //console.log("☆Counter Update1 [" + gi_updateCountMs + "]" ); } }else{ //フォーカスの判定が外れたのでカウントリセット gi_updateCountMs = giA_updateIntervalMs[gi_dispMode]; gi_displayPaused = 1; //console.log("☆Wait for current control [" + gi_updateCountMs + "]" ); } }else{ //先頭に戻された次回に少し待って更新がかかるようにする gi_displayPaused = 1; //手動更新の操作でトリガが掛かった後ならカウンタリセット、それ以外でスクロール位置が先頭に戻ったら少し後にトリガ if( gi_onTopWaitMs != 0 && ( gdt_temp.getTime() - gdt_lastTriggerTime.getTime() > gi_manualUpdateIntervalSec * 1000 ) ){ gi_updateCountMs = giA_updateIntervalMs[gi_dispMode] - gi_onTopWaitMs; }else{ gi_updateCountMs = 0; } if(gi_updateCountMs < 1000 ) gi_updateCountMs = 0; //console.log("☆Wait for window top [" + gi_updateCountMs + "]" ); } } //更新トリガ処理 function execTrigger(onAuto, buttonId){ //onAuto: true=自動処理によるトリガ / false=手動更新によるトリガ //buttonId : 手動トリガ時のボタンインデックス var max, min, w1, msg, e, e0, e1, tm = new Date(); if( ! onAuto && giA_updateContinuousButton[buttonId] ){ w1 = getDialogWidth(); msg = "
[" + toFormatedDateString(new Date()) + "]
新着を現在の最新より上に積むのを試みます
"; msg += "
"; msg += "
"; //更新トリガ前の状態を保存しておく clickNewestTweetPreSave(); dispDebugTextWithTime("Cont0 : PreSave Continuous Mode", LOG_TRC); } if( gi_dispMode == MODE_HOME ){ //メニューのHomeを押す事で更新トリガさせる var homeButton = document.body.querySelectorAll('a[data-testid="AppTabBar_Home_Link"]'); if(homeButton.length > 0) { //トリガ homeButton[0].click(); //更新トリガの時間を記録 gdt_lastTriggerTime = tm; //遅延ワンショット実行 execDelayOneShotShortTimer(true); //console.log("★Home Button Update"); //トリガ後に先頭記事に遷移して新着を上に積む if( ! onAuto && giA_updateContinuousButton[buttonId] ){ //終了判定のため次のDOMイベントを待つ gf_continuousDOMWaiting = true; gi_continuousMode = 1; gi_DOMEventRecvCount = 0; gi_continuousPhase = CONT_WAITING; //エラー停止した場合のポップアップは設定に関わらず出ているので消す closePopupContinuousAll(true); if( gi_updateContinuousDispPopup ){ gelm_fixedPopupContinuousStart = dispPopupMessage(msg, -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT, true, false); e = document.getElementById('ELM_CONTMODE_BTN1'); if( e !== null ){ e.onclick = function(){ clickNewestTweetTimeout(false); } } } window.setTimeout( clickNewestTweetStart, gi_updateContimuousDelayTimeMs, 0 ); gtmr_timeoutContinuous = window.setTimeout( clickNewestTweetTimeout, gi_updateContinuousResultTimeMs * gi_updateContinuousDOMPastCycle * 5, true ); } } }else if( gi_dispMode == MODE_LIST || gi_dispMode == MODE_SEAR || gi_dispMode == MODE_USER ){ if( gi_dispMode != MODE_SEAR || ! gi_disableCssOnSearchUpdate ){ //スクロール操作によって更新トリガさせる gi_execTriggerByScroll = 1; window.scrollTo(0, window.innerHeight); window.setTimeout( function(){ gi_execTriggerByScroll = 1; window.scrollTo(0, 0); }, SCROLL_TYPE_TRIGGER_WAIT ); }else{ //検索ページでは一部環境でCSSが起因してか更新が掛からないので一旦印をつけてCSSを無効にする e0 = document.querySelectorAll('body:not([' + gstr_scrSearchUpdate +'])'); if( e0.length > 0 ){ e0[0].setAttribute( gstr_scrSearchUpdate, "" ); } //スクロール操作によって更新トリガさせる window.setTimeout( function(){ gi_execTriggerByScroll = 1; window.scrollTo(0, window.innerHeight); }, SCROLL_TYPE_TRIGGER_WAIT + gi_disableCssSearchWaitMs ); window.setTimeout( function(){ gi_execTriggerByScroll = 1; window.scrollTo(0, 0); }, (SCROLL_TYPE_TRIGGER_WAIT + gi_disableCssSearchWaitMs) * 2 ); //CSS無効を戻す window.setTimeout( function(){ var e0 = document.querySelectorAll('body[' + gstr_scrSearchUpdate +']'); if( e0.length > 0 ){ e0[0].removeAttribute( gstr_scrSearchUpdate ); } }, (SCROLL_TYPE_TRIGGER_WAIT + gi_disableCssSearchWaitMs) * 3 ); } //更新トリガの時間を記録 gdt_lastTriggerTime = tm; //遅延ワンショット実行 execDelayOneShotShortTimer(true); //トリガ後に先頭記事に遷移して新着を上に積む if( ! onAuto && giA_updateContinuousButton[buttonId] ){ //終了判定のため次のDOMイベントを待つ gf_continuousDOMWaiting = true; gi_continuousMode = 1; gi_DOMEventRecvCount = 0; gi_continuousPhase = CONT_WAITING; //エラー停止した場合のポップアップは設定に関わらず出ているので消す closePopupContinuousAll(true); if( gi_updateContinuousDispPopup ){ gelm_fixedPopupContinuousStart = dispPopupMessage(msg, -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT, true, false); } window.setTimeout( clickNewestTweetStart, gi_updateContimuousDelayTimeMs, 0 ); gtmr_timeoutContinuous = window.setTimeout( clickNewestTweetTimeout, gi_updateContinuousResultTimeMs * gi_updateContinuousDOMPastCycle * 5, true ); e = document.getElementById('ELM_CONTMODE_BTN1'); if( e !== null ){ e.onclick = function(){ clickNewestTweetTimeout(false); } } } //console.log("★Scroll Update"); /* //参考ソース https://github.com/natsuyasai/TwitterAutoReloadScript // aタグの中から上タブ要素かつ現在アクティブになっている要素を取得し、クリックイベントを発火させる・・・手動で上部タブをクリックしても更新かかってくれませんね、これは旧仕様用でしょう e0 = document.querySelectorAll('a[role="tab"][aria-selected="true"]'); if( e0.length > 0 ) { e0[0].click(); } */ }else if( gi_dispMode == MODE_NOTI ){ //通知ページの場合はDM新着チェック checkDMNotification(); //通知ページの場合は新着表示クリア clearNewNotification(); } } //表示用エレメントのチェック〜無ければ捜索 function findDisplayElements(){ //カウンタ表示用のエレメントを捜索 if( gelm_dispInfo === null ){ //構築前に消去する removeInfoButtonElements(); if( gi_dispMode == MODE_HOME ){ //Home gelm0 = document.querySelectorAll('a[role="tab"][aria-selected="true"]'); if( gelm0.length > 0 ){ gelm1 = gelm0[0].firstElementChild; if( gelm1 !== null ){ gelm2 = gelm1.firstElementChild; if( gelm2 !== null ){ //情報表示&ボタン類を追加する場所 setupElement(gelm2); //「フォロー中」を「Home」に置換 gelm3 = gelm2.firstElementChild; if( gelm3 !== null && HOME_TL_NAME != "" ){ gelm3.textContent = HOME_TL_NAME; } //情報表示をする場所 //gelm_dispInfo = gelm2.firstElementChild; //console.log("★find: Element"); } } } }else if( gi_dispMode == MODE_LIST ){ //List //リスト作成者のアカウント名に表示項目を追加 gelm0 = document.querySelectorAll('h2[dir="ltr"][aria-level="2"][role="heading"]'); if( gelm0.length > 0 ){ gelm4 = gelm0[0].firstElementChild; if( gelm4 !== null ){ //情報表示&ボタン類を追加する場所 setupElement(gelm4); } } }else if( gi_dispMode == MODE_USER ){ //User //ユーザーのツイート数に表示項目を追加 gelm0 = document.querySelectorAll('h2[dir="ltr"][aria-level="2"][role="heading"]'); if( gelm0.length > 0 ){ gelm4 = gelm0[0].firstElementChild; if( gelm4 !== null ){ gelm5 = gelm4.firstElementChild; if( gelm5 !== null ){ //情報表示&ボタン類を追加する場所 setupElement(gelm5); } } //console.log("★find: Element"); } }else if( gi_dispMode == MODE_NOTI ){ //Notification gelm0 = document.querySelectorAll('h2[dir="ltr"][aria-level="2"][role="heading"]'); if( gelm0.length > 0 ){ setupElement(gelm0[0]); gelm_btnAutoOff.style.display = "none"; //console.log("★find: Element"); } }else if( gi_dispMode == MODE_SEAR ){ //Search //検索ページの最新に表示項目を追加 gelm0 = document.querySelectorAll('div[data-testid="ScrollSnap-SwipeableList"]'); if( gelm0.length > 0 ){ gelm1 = gelm0[0].firstElementChild; if( gelm1 !== null ){ gelm2 = gelm1.firstElementChild; if( gelm2 !== null ){ gelm3 = gelm2.nextElementSibling; if( gelm3 !== null ){ gelm4 = gelm3.firstElementChild; if( gelm4 !== null ){ gelm5 = gelm4.firstElementChild; if( gelm5 !== null ){ gelm6 = gelm5.firstElementChild; if( gelm6 !== null ){ //情報表示&ボタン類を追加する場所 setupElement(gelm6); //console.log("★find: Element"); } } } } } } } } } } //情報の表示更新〜色替え function updateDisplayInfo(){ var tmp, str, strLastRecvTime = toFormatedTimeString(gdt_lastRecvTime); //更新に関する情報を表示する if( gi_initComplete != 0 || gi_displayPaused ){ //表示用エレメントのチェック〜無ければ捜索 findDisplayElements(); //カウンタを更新 if( gelm_dispInfo !== null ){ tmp = giA_updateIntervalMs[gi_dispMode] - gi_updateCountMs; if(tmp < 1000 ) tmp = 0; //フォーカスを持ったタブのみカウントを都度更新(全部に対して行うと重すぎる) //設定内容を設定先と比較して違ったら代入するようにしているのは、代入によって内部でDOM更新が走り処理が重くなるため if( (document.visibilityState === "visible" && document.hasFocus() === true || gi_onButtonHover ) && gi_dispMode != MODE_NOTI ){ if( ! gi_displayPaused ){ if( ! gi_noCountDownDisp || gi_onButtonHover ){ //TXT_COUNTDOWNTIM = "[ #### / $$$$$$$$ ]"; str = TXT_COUNTDOWNTIM.replace("####", ("0000" + (tmp / 1000)).slice(-4) ).replace("$$$$$$$$",strLastRecvTime) }else{ //TXT_NOCOUNTDOWNT = "[ Active/ $$$$$$$$ ]"; str = TXT_NOCOUNTDOWNT.replace("$$$$$$$$",strLastRecvTime) } if(gelm_dispInfo.textContent != str) gelm_dispInfo.textContent = str; if( tmp == 0 ){ gi_colorType = TYPE_UPDATE; }else if( tmp <= 10000 ){ //強制リロード間際の色替え if( gdt_temp.getTime() - gdt_lastRecvTime.getTime() > (giA_reloadTimeoutSec[gi_dispMode] * 1000 - 10000) && giA_reloadTimeoutSec[gi_dispMode] > 0 ){ gi_colorType= TYPE_RELOAD; }else{ gi_colorType = TYPE_UPSOON; } }else{ gi_colorType = TYPE_ACTIVE; } }else{ if( ! gi_enableDomTimeAutoOff ){ //TXT_PAUSEDUPDATE = "[ Paused Refresh...]"; str = TXT_PAUSEDUPDATE; }else{ //TXT_PAUSEDUPDAT2 = "[ Paused/ $$$$$$$$ ]"; str = TXT_PAUSEDUPDAT2.replace("$$$$$$$$",strLastRecvTime); } if(gelm_dispInfo.textContent != str) gelm_dispInfo.textContent = str; gi_colorType = TYPE_PAUSED; } }else{ //最後にレコード更新があがってきたタイムスタンプを表示 if( ! gi_displayPaused || gi_dispMode == MODE_NOTI ){ //TXT_LATESTNOFOCS = "[ Auto / $$$$$$$$ ]"; str = TXT_LATESTNOFOCS.replace("$$$$$$$$",strLastRecvTime); if(gelm_dispInfo.textContent != str) gelm_dispInfo.textContent = str; if( tmp == 0 && gi_dispMode != MODE_NOTI ){ gi_colorType = TYPE_UPDATE; }else if( tmp <= 10000 && gi_dispMode != MODE_NOTI ){ //強制リロード間際の色替え if( gdt_temp.getTime() - gdt_lastRecvTime.getTime() > (giA_reloadTimeoutSec[gi_dispMode] * 1000 - 10000) && giA_reloadTimeoutSec[gi_dispMode] > 0 ){ gi_colorType= TYPE_RELOAD; }else{ gi_colorType = TYPE_UPSOON; } }else{ //通知ページ専用処理 if( gi_dispMode == MODE_NOTI ){ //強制リロード間際の色替え if( gdt_temp.getTime() - gdt_lastRecvTime.getTime() > (giA_reloadTimeoutSec[gi_dispMode] * 1000 - 10000) && giA_reloadTimeoutSec[gi_dispMode] > 0 ){ gi_colorType= TYPE_RELOAD; /* }else if(gf_flgClearNotification){ //新着クリア中の表示 forceUpdateColor(COLOR_FGCOLOR,TXT_CLEARNEWNOTI); gi_colorType= 0; */ }else{ gi_colorType= TYPE_ACTIVE; } }else{ gi_colorType = TYPE_ACTIVE; } } }else{ if( ! gi_enableDomTimeAutoOff ){ //TXT_PAUSEDUPDATE = "[ Paused Refresh...]"; str = TXT_PAUSEDUPDATE; }else{ //TXT_PAUSEDUPDAT2 = "[ Paused/ $$$$$$$$ ]"; str = TXT_PAUSEDUPDAT2.replace("$$$$$$$$",strLastRecvTime); } if(gelm_dispInfo.textContent != str) gelm_dispInfo.textContent = str; gi_colorType = TYPE_PAUSED; } } if(gelm_dispInfo.style.fontSize != gstrA_titleSize[gi_dispMode]) gelm_dispInfo.style.fontSize = gstrA_titleSize[gi_dispMode]; //表示部をクリックしても更新トリガしない期間の色替え if( gi_colorType != TYPE_RELOAD && gi_colorType != 0 ){ if( gdt_temp.getTime() - gdt_lastTriggerTime.getTime() <= gi_manualUpdateIntervalSec * 1000 ){ gi_colorType = TYPE_HOLDTM; } } //ボタンコントロールの色替え if(gi_colorType == TYPE_UPDATE){ if(gelm_dispInfo.style.color != COLOR_UPDATE) gelm_dispInfo.style.color = COLOR_UPDATE; if(gelm_btnInterval.style.color != COLOR_INT_UPDATE) gelm_btnInterval.style.color = COLOR_INT_UPDATE; if(gelm_btnHelp.style.color != COLOR_HLP_UPDATE) gelm_btnHelp.style.color = COLOR_HLP_UPDATE; if( gi_modeAutoOff == 1 ){ if(gelm_btnAutoOff.style.color != COLOR_AUT_DISABL) gelm_btnAutoOff.style.color = COLOR_AUT_DISABL; }else{ if(gelm_btnAutoOff.style.color != COLOR_AUT_UPDATE) gelm_btnAutoOff.style.color = COLOR_AUT_UPDATE; } //短周期タイマの稼動状態 if( gi_idleShortTimer == 1 ){ if( gtmr_shortTimer === null && ! gf_oneShotShortTimer ){ //短周期タイマ停止中 if(gelm_btnShort.style.color != COLOR_IDL_DISABL) gelm_btnShort.style.color = COLOR_IDL_DISABL; }else{ //短周期タイマ動作中 if(gelm_btnShort.style.color != COLOR_IDL_UPDATE) gelm_btnShort.style.color = COLOR_IDL_UPDATE; } }else{ //短周期タイマ常時稼動モード if(gelm_btnShort.style.color != COLOR_ALW_UPDATE) gelm_btnShort.style.color = COLOR_ALW_UPDATE; } }else if(gi_colorType == TYPE_UPSOON){ if(gelm_dispInfo.style.color != COLOR_UPSOON) gelm_dispInfo.style.color = COLOR_UPSOON; if(gelm_btnInterval.style.color != COLOR_INT_UPSOON) gelm_btnInterval.style.color = COLOR_INT_UPSOON; if(gelm_btnHelp.style.color != COLOR_HLP_UPSOON) gelm_btnHelp.style.color = COLOR_HLP_UPSOON; if( gi_modeAutoOff == 1 ){ if(gelm_btnAutoOff.style.color != COLOR_AUT_DISABL) gelm_btnAutoOff.style.color = COLOR_AUT_DISABL; }else{ if(gelm_btnAutoOff.style.color != COLOR_AUT_UPSOON) gelm_btnAutoOff.style.color = COLOR_AUT_UPSOON; } //短周期タイマの稼動状態 if( gi_idleShortTimer == 1 ){ if( gtmr_shortTimer === null && ! gf_oneShotShortTimer ){ //短周期タイマ停止中 if(gelm_btnShort.style.color != COLOR_IDL_DISABL) gelm_btnShort.style.color = COLOR_IDL_DISABL; }else{ //短周期タイマ動作中 if(gelm_btnShort.style.color != COLOR_IDL_UPSOON) gelm_btnShort.style.color = COLOR_IDL_UPSOON; } }else{ //短周期タイマ常時稼動モード if(gelm_btnShort.style.color != COLOR_ALW_UPSOON) gelm_btnShort.style.color = COLOR_ALW_UPSOON; } }else if(gi_colorType == TYPE_ACTIVE){ if(gelm_dispInfo.style.color != COLOR_ACTIVE) gelm_dispInfo.style.color = COLOR_ACTIVE; if(gelm_btnInterval.style.color != COLOR_INT_ACTIVE) gelm_btnInterval.style.color = COLOR_INT_ACTIVE; if(gelm_btnHelp.style.color != COLOR_HLP_ACTIVE) gelm_btnHelp.style.color = COLOR_HLP_ACTIVE; if( gi_modeAutoOff == 1 ){ if(gelm_btnAutoOff.style.color != COLOR_AUT_DISABL) gelm_btnAutoOff.style.color = COLOR_AUT_DISABL; }else{ if(gelm_btnAutoOff.style.color != COLOR_AUT_ACTIVE) gelm_btnAutoOff.style.color = COLOR_AUT_ACTIVE; } //短周期タイマの稼動状態 if( gi_idleShortTimer == 1 ){ if( gtmr_shortTimer === null && ! gf_oneShotShortTimer ){ //短周期タイマ停止中 if(gelm_btnShort.style.color != COLOR_IDL_DISABL) gelm_btnShort.style.color = COLOR_IDL_DISABL; }else{ //短周期タイマ動作中 if(gelm_btnShort.style.color != COLOR_IDL_ACTIVE) gelm_btnShort.style.color = COLOR_IDL_ACTIVE; } }else{ //短周期タイマ常時稼動モード if(gelm_btnShort.style.color != COLOR_ALW_ACTIVE) gelm_btnShort.style.color = COLOR_ALW_ACTIVE; } }else if(gi_colorType == TYPE_PAUSED){ if(gelm_dispInfo.style.color != COLOR_PAUSED) gelm_dispInfo.style.color = COLOR_PAUSED; if(gelm_btnInterval.style.color != COLOR_INT_PAUSED) gelm_btnInterval.style.color = COLOR_INT_PAUSED; if(gelm_btnHelp.style.color != COLOR_HLP_PAUSED) gelm_btnHelp.style.color = COLOR_HLP_PAUSED; if( gi_modeAutoOff == 1 ){ if(gelm_btnAutoOff.style.color != COLOR_AUT_DISABL) gelm_btnAutoOff.style.color = COLOR_AUT_DISABL; }else{ if(gelm_btnAutoOff.style.color != COLOR_AUT_PAUSED) gelm_btnAutoOff.style.color = COLOR_AUT_PAUSED; } //短周期タイマの稼動状態 if( gi_idleShortTimer == 1 ){ if( gtmr_shortTimer === null && ! gf_oneShotShortTimer ){ //短周期タイマ停止中 if(gelm_btnShort.style.color != COLOR_IDL_DISABL) gelm_btnShort.style.color = COLOR_IDL_DISABL; }else{ //短周期タイマ動作中 if(gelm_btnShort.style.color != COLOR_IDL_PAUSED) gelm_btnShort.style.color = COLOR_IDL_PAUSED; } }else{ //短周期タイマ常時稼動モード if(gelm_btnShort.style.color != COLOR_ALW_PAUSED) gelm_btnShort.style.color = COLOR_ALW_PAUSED; } }else if(gi_colorType == TYPE_HOLDTM){ if(gelm_dispInfo.style.color != COLOR_HOLDTM) gelm_dispInfo.style.color = COLOR_HOLDTM; if(gelm_btnInterval.style.color != COLOR_INT_HOLDTM) gelm_btnInterval.style.color = COLOR_INT_HOLDTM; if(gelm_btnHelp.style.color != COLOR_HLP_HOLDTM) gelm_btnHelp.style.color = COLOR_HLP_HOLDTM; if( gi_modeAutoOff == 1 ){ if(gelm_btnAutoOff.style.color != COLOR_AUT_DISABL) gelm_btnAutoOff.style.color = COLOR_AUT_DISABL; }else{ if(gelm_btnAutoOff.style.color != COLOR_AUT_HOLDTM) gelm_btnAutoOff.style.color = COLOR_AUT_HOLDTM; } //短周期タイマの稼動状態 if( gi_idleShortTimer == 1 ){ if( gtmr_shortTimer === null && ! gf_oneShotShortTimer ){ //短周期タイマ停止中 if(gelm_btnShort.style.color != COLOR_IDL_DISABL) gelm_btnShort.style.color = COLOR_IDL_DISABL; }else{ //短周期タイマ動作中 if(gelm_btnShort.style.color != COLOR_IDL_HOLDTM) gelm_btnShort.style.color = COLOR_IDL_HOLDTM; } }else{ //短周期タイマ常時稼動モード if(gelm_btnShort.style.color != COLOR_ALW_HOLDTM) gelm_btnShort.style.color = COLOR_ALW_HOLDTM; } }else if(gi_colorType == TYPE_RELOAD){ if(gelm_dispInfo.style.color != COLOR_RELOAD) gelm_dispInfo.style.color = COLOR_RELOAD; if(gelm_btnInterval.style.color != COLOR_INT_RELOAD) gelm_btnInterval.style.color = COLOR_INT_RELOAD; if(gelm_btnHelp.style.color != COLOR_HLP_RELOAD) gelm_btnHelp.style.color = COLOR_HLP_RELOAD; if( gi_modeAutoOff == 1 ){ if(gelm_btnAutoOff.style.color != COLOR_AUT_DISABL) gelm_btnAutoOff.style.color = COLOR_AUT_DISABL; }else{ if(gelm_btnAutoOff.style.color != COLOR_AUT_RELOAD) gelm_btnAutoOff.style.color = COLOR_AUT_RELOAD; } //短周期タイマの稼動状態 if( gi_idleShortTimer == 1 ){ if( gtmr_shortTimer === null && ! gf_oneShotShortTimer ){ //短周期タイマ停止中 if(gelm_btnShort.style.color != COLOR_IDL_DISABL) gelm_btnShort.style.color = COLOR_IDL_DISABL; }else{ //短周期タイマ動作中 if(gelm_btnShort.style.color != COLOR_IDL_RELOAD) gelm_btnShort.style.color = COLOR_IDL_RELOAD; } }else{ //短周期タイマ常時稼動モード if(gelm_btnShort.style.color != COLOR_ALW_RELOAD) gelm_btnShort.style.color = COLOR_ALW_RELOAD; } } } } gf_oneShotShortTimer = false; } //通常パターン以外での色替え(手動の更新操作やエラー発生時などのモニタリング用) function forceUpdateColor(rgba,txt){ //rgba: 表示色 //txt: 表示文字列 if( gelm_dispInfo === null || gelm_dispInfo.textContent === null || gelm_btnInterval === null || gelm_btnHelp === null || gelm_btnAutoOff === null || gelm_btnShort === null ) return; gelm_dispInfo.textContent = txt; gelm_dispInfo.style.color = rgba; gelm_btnHelp.style.color = COLOR_BGCOLOR; gelm_btnInterval.style.color = COLOR_GRAY; gelm_btnAutoOff.style.color = COLOR_GRAY; gelm_btnShort.style.color = COLOR_GRAY; } /************************************************************ 長周期タイマ処理関数 ************************************************************/ function execLongSpanTimer(){ //10秒サイクル処理 if( ++gi_longTimerCount10 >= gi_maxLongTimerCount10 ){ gi_longTimerCount10 = 0; exec10SecTimer(); } //60秒サイクル処理を10秒サイクル処理から半サイクルずらして実行 if( gi_longTimerCount10 == Math.floor(gi_maxLongTimerCount10 / 2) ){ if( ++gi_longTimerCount60 >= gi_maxLongTimerCount60 ){ gi_longTimerCount60 = 0; exec60secTimer(); } } } //10秒間隔処理 function exec10SecTimer(){ var count, e; //消し残りポップアップ救済 closePopupMessage(); //新着の確認 if( gi_dispMode == MODE_HOME ){ if( gi_idleShortTimer && gtmr_shortTimer === null && gelm_btnCount !== null && gi_countPosition > BTN4_POSITION_NONE ){ e = document.querySelectorAll(HOME_NEW_TWEET_BASE); if( e.length > 0 ){ count = (e[0].textContent + "").replace(" 件のポストを表示","").replace(",","").replace("\.",""); if( count !== null && count !== undefined && (gi_numberNewTweetCount != Number(count) || gelm_btnCount.textContent == "" ) ){ dispDebugTextWithTime("exec10SecTimer : NewTweet = " + Number(count) ); replaceElementsOneShot(); } }else{ if( gi_numberNewTweetCount > 0 ){ dispDebugTextWithTime("exec10SecTimer : NewTweet = 0" ); replaceElementsOneShot(); } } } } //短周期処理にて未処理のレコードがあるかチェック e = document.querySelectorAll( ARTICLE_LIST_BASE ); if( e.length > 0 ){ //短周期タイマのワンショット dispDebugTextWithTime("exec10SecTimer : replaceElementsOneShot", LOG_SHRT ); replaceElementsOneShot(); } } //60秒間隔処理 function exec60secTimer(){ var dt = new Date(), timesub = 0, updsub = 0, interval = 0, recvpast = 0; rebuildInfoButtons(); //最後のDOM受信から一定時間経過したら再構築する timesub = dt.getTime() - gdt_lastDomTime.getTime(); interval = OBSERVER_REBUILDTIMESEC * 1000; //レコード受信から一定時間が経過してない時には再構築しない updsub = dt.getTime() - gdt_lastRecvTime.getTime(); recvpast = OBSERVER_RECVPASTTIMESEC * 1000; /* //自動モード中で更新インターバルのほうが長い場合は更新インターバルで判定する if( giA_updateIntervalMs[gi_dispMode] > interval && gi_modeAutoOff == 0 && gi_displayPaused == 0 ){ interval = giA_updateIntervalMs[gi_dispMode]; } */ if( timesub > interval && updsub > recvpast ){ dispDebugTextWithTime("exec60secTimer : DOM past=" + timesub + "ms / Recv past=" + updsub + "ms", LOG_TRC ); gf_firstDOM = true; //Observerが無効になるケースがあるのでイベントが上がるか要素追加してみる(DOM更新が上がっていなければobserverを張り直す) gi_testEventMode = 1; var dmy = document.createElement('DIV'); dmy.textContent = "[PseudoTweetDeck] Script Loading..."; if( gelmObserv !== null ){ gelmObserv.appendChild(dmy); gelmObserv.removeChild(dmy); window.setTimeout( checkDOMEvent, CHECK_DOM_INTERVAL ); dispDebugTextWithTime("exec60secTimer : checkDOMEvent()", LOG_TRC); }else{ //そもそもエレメントが無効になっていたら再構築 dispDebugTextWithTime("exec60secTimer : clearElements()", LOG_ERR); gi_initComplete = 0; clearElements(); } } } /************************************************************ 短周期タイマ処理関数 ************************************************************/ const HOME_NEW_TWEET = '[role="button"][class="css-175oi2r r-1777fci r-dfe81l r-13qz1uu r-1loqt21 r-o7ynqc r-6416eg r-1ny4l3l"]'; const HOME_NEW_TWEET_BASE = 'div[aria-label="タイムライン: ホームタイムライン"] div[data-testid="cellInnerDiv"]:has(' + HOME_NEW_TWEET + ')'; const ARTICLE_LIST_BASE = 'main div[data-testid="primaryColumn"] section article a[href*="/status/"] time:not([' + TIME_FIXED + '])'; const ARTICLE_LIST_SUB = 'main div[data-testid="primaryColumn"] section article div:not(:has(a[href*="/status/"])) time:not([' + TIME_FIXED_SUB + '])'; //単発で短周期処理の実行 function replaceElementsOneShot(){ return replaceElements(true); } //短周期処理(タイムスタンプ置換、表示タイトル変更、さらに表示系の自動押下) function replaceElements(oneShot=false){ //oneShot: true=短周期タイマ停止中のワンショット実行 //画面遷移を判定し、変わっていたら初期処理をやりなおす if( isChangedDisp() ){ window.setTimeout( replaceElements, gi_shortIntervalMs ); return; } if( gi_dispMode != MODE_NULL ){ if( gi_initComplete == 0 ){ dispDebugTextWithTime("replaceElements : initComplete=0, clearElements()"); window.setTimeout( clearElements, gi_shortIntervalMs ); return; } } //情報表示部にワンショット実行の色替えをするためのフラグ設定 gf_oneShotShortTimer = oneShot; //新たに処理をした読込レコードがあったかフラグを初期化 タイムスタンプ置換前処理 gf_newArticleRecv = false; //タイムスタンプ置換・既読マークを全アーティクルに対して実施する replaceTimeStamp(); //引用RT先のタイムスタンプ置換 replaceTimeStampSub(); //新着積み上げ更新の進行を管理 if( gi_continuousMode ){ if( gf_newArticleRecv && gf_continuousDOMWaiting && ( gi_continuousPhase == CONT_DOMWAIT || gi_continuousPhase == CONT_WAITCONT ) ){ gi_DOMEventRecvCount++; dispDebugTextWithTime("replaceElements : New articles recieved, DOMWaiting [" + gi_DOMEventRecvCount + "]"); } } //ワンショット実行などで新レコードを処理したらタイマ再開させる if( gf_newArticleRecv ){ dispDebugTextWithTime("replaceElements : New articles recieved[" + ("00" + gi_articleRecv).slice(-2) + "]", LOG_SHRT); if( gelm_btnCount !== null && gi_countPosition > BTN4_POSITION_NONE && gi_dispNumberRecvTweetCount && gi_dispMode != MODE_NOTI ){ //受信件数を表示 var NewText = "(" + gi_articleRecv + ")"; if( gelm_btnCount.textContent != NewText ){ gelm_btnCount.textContent = NewText; gelm_btnCount.style.color = COLOR_GRAY; } } restartShortTimerInterval(); } //受信レコード処理フラグをクリア gf_newArticleRecv = false; if( gi_dispMode != MODE_NULL ){ //新着記事の件数を処理 convertNewTweetCount(oneShot); //リストページは何故か一定以上スクロールするとヘッダ非表示のCSSが悪さをするらしくDOM更新が止まらなくなるのを抑止 execListPageSplitScroll(); //重複記事の非表示 removeSameArticle(); } //NGワード判定 execNGfilter(); if( gi_dispMode != MODE_NULL ){ //画像リンクの処理 settingOpenImageNewTab(); //タブタイトルの置換 replaceTabTitle(); //「さらに表示」を処理 execMoreTweet(); } } //タイムスタンプ置換(+既読チェックボックス設置) function replaceTimeStamp(){ gi_articleRecv = 0; var u = getPageURL(); //タイムスタンプ置換・既読マークを全アーティクルに対して実施する document.querySelectorAll( ARTICLE_LIST_BASE ).forEach(function(e){ var a = e.parentNode; var b = a.parentNode; var h = a.getAttribute("href"); var s0 = e.getAttribute("datetime"); var s1 = toFormatedDateString(new Date(s0)); var span; if( gi_replaceTimeStamp ){ //置換をする設定の場合 span = document.createElement("span"); span.setAttribute("datetime", s0); span.setAttribute("local-datetime", s1); span.textContent = s1; a.appendChild(span); a.removeChild(e); }else{ //置換をしない設定の場合は目印をつけておかないと毎回チェックボックスが増えてしまう e.setAttribute(TIME_FIXED,""); } if( gi_dispMode != MODE_NULL ){ //既読マークの処理(タイムスタンプ置換の処理済みレコードを既読マークの処理済みと兼用しているのでタイムスタンプ処理のループ内で行う) settingReadPoint(u, h, s1, b); } gi_articleRecv++; gf_newArticleRecv = true; gf_DOMEventRecv = false; gdt_lastRecvTime = new Date(); }); } //引用RT先のタイムスタンプ置換 function replaceTimeStampSub(){ document.querySelectorAll( ARTICLE_LIST_SUB ).forEach(function(e){ var a = e.parentNode; var s0 = e.getAttribute("datetime"); var s1 = toFormatedDateString(new Date(s0)); var span; if( gi_replaceTimeStamp ){ //置換をする設定の場合 span = document.createElement("span"); span.setAttribute("datetime", s0); span.setAttribute("local-datetime", s1); span.textContent = s1; a.appendChild(span); a.removeChild(e); }else{ //置換をしない設定の場合は目印をつけておかないと毎回処理されてしまう e.setAttribute(TIME_FIXED_SUB,""); } }); } //新着記事の件数を処理 function convertNewTweetCount(oneShot){ //oneShot: 短周期処理が単発で呼ばれた=true var e0, e1, e2, e3, idx, dt = new Date(), OldText = "", NewText = ""; if( gi_dispMode == MODE_HOME ){ //新着表示をクリックした場合にも更新時間を記録 var strDispCount = ""; e0 = document.querySelectorAll('body'); if( e0.length > 0 ){ //アーティクル増減可変部 e1 = e0[0].querySelectorAll(HOME_NEW_TWEET_BASE); if( e1.length > 0 ){ if( e0[0].getAttribute(gstr_scrNewTweetAttr) == null){ if( gi_hideNumberNewTweet ){ e0[0].setAttribute(gstr_scrNewTweetAttr, 'false'); e1[0].display = "none"; // console.log("★replaceElements0 SET:" + gstr_scrNewTweetAttr + " = false"); }else{ e0[0].setAttribute(gstr_scrNewTweetAttr, 'true'); e1[0].display = null; //console.log("★replaceElements0 SET:" + gstr_scrNewTweetAttr + " = true"); } } e2 = e1[0].querySelectorAll( HOME_NEW_TWEET + ':not([' + gstr_scrNewTweetAttr + '])'); for( idx=0; idx < e2.length; idx++ ){ //イベントリスナーを多重登録しないよう目印をつける e2[idx].setAttribute(gstr_scrNewTweetAttr, 'true'); //console.log("★replaceElements0 新着のエレメント発見[" + idx + "]"); e2[idx].addEventListener('click', onClickNewTweet); } if( gi_dispNumberNewTweetCount && gelm_btnCount !== null && gi_countPosition > BTN4_POSITION_NONE ){ OldText = gelm_btnCount.textContent + ""; e3 = e1[0].querySelectorAll( HOME_NEW_TWEET + ' span'); if( e3.length > 0 ){ //新着表示OFFの時のみ件数を表示する if( gi_hideNumberNewTweet ){ //新着件数表示から件数を獲得 gi_numberNewTweetCount = (e3[0].textContent + "").replace(" 件のポストを表示","").replace(",","").replace("\.",""); if( gi_numberNewTweetCount == "" ){ gi_numberNewTweetCount = 0; }else{ gi_numberNewTweetCount = Number(gi_numberNewTweetCount); } strDispCount = (((gelm_btnCount.textContent + "").replace("[","")).replace("]","")).trim(); if( gi_numberNewTweetCount != Number(strDispCount) ){ dispDebugTextWithTime("convertNewTweetCount OneShot=" + oneShot + " : NewTweet(A) = " + gi_numberNewTweetCount, LOG_SHRT ); } NewText = "[" + gi_numberNewTweetCount + "]"; } } //新着表示がなくなった(このパターンは無さそうだが) if( NewText == "" || gi_numberNewTweetCount == 0 ){ NewText = ""; gi_numberNewTweetCount = 0; } //受信件数表示中との優先順位判定 if( OldText != NewText && (OldText.indexOf("(") != 0 && NewText == "" || NewText != "" ) ){ gelm_btnCount.textContent = NewText; gelm_btnCount.style.color = COLOR_RECVCOUNT; if( gi_numberNewTweetCount == 0 ){ dispDebugTextWithTime("convertNewTweetCount OneShot=" + oneShot + " : NewTweet(B) = 0", LOG_SHRT ); } } }else{ //新着表示なし設定時の受信件数表示 if( gelm_btnCount !== null && gi_countPosition > BTN4_POSITION_NONE ){ OldText = gelm_btnCount.textContent + ""; NewText = ""; if( OldText != NewText && OldText.indexOf("(") != 0 ){ gelm_btnCount.textContent = NewText; dispDebugTextWithTime("convertNewTweetCount OneShot=" + oneShot + " : NewTweet(C) = 0", LOG_SHRT ); } } gi_numberNewTweetCount = 0; } }else{ //新着表示がなくなった if( gelm_btnCount !== null && gi_countPosition > BTN4_POSITION_NONE ){ OldText = gelm_btnCount.textContent + ""; NewText = ""; if( OldText != NewText && OldText.indexOf("(") != 0 ){ gelm_btnCount.textContent = NewText; dispDebugTextWithTime("convertNewTweetCount OneShot=" + oneShot + " : NewTweet(D) = 0", LOG_SHRT ); } } gi_numberNewTweetCount = 0; } }else{ //body未構築 gi_numberNewTweetCount = 0; dispDebugTextWithTime("convertNewTweetCount OneShot=" + oneShot + " : NewTweet(E) = 0", LOG_SHRT ); } } } //タブタイトルの置換処理 function replaceTabTitle(){ //console.log("★ 1 Title=" + document.title); var idx1, idx2, t = document.title + ""; if( t.indexOf('@') != -1 ){ // Listページ タブタイトルの変更 「@USERNAME/ListName」→「ListName」 if( window.location.href.indexOf(TWITTER_URL + PATH_LIST) !== -1 ){ idx1 = t.indexOf('@'); idx2 = t.indexOf('/'); if( idx1 !== -1 && idx2 !== -1 ) t = t.substr(idx2+1); }else{ // Userページ タブタイトルの変更 「Posts with replies by 」など削除 t = ((t.replace('Posts with replies by ','')).replace('Media posts by ','')).replace('Posts liked by ',''); // 通知があると先頭に(1)とかが付くのでこのあとのタブタイトル置換でidx2の値がidx1より手前になってしまうのを回避 // 「(1) DISPNAME (@USERNAME) / X」→「DISPNAME (@USERNAME) / X」 // 「(1) DISPNAME(@USERNAME)さん / X」→「DISPNAME(@USERNAME)さん / X」 idx1 = t.indexOf(")"); idx2 = t.indexOf("@"); if( t.substr(0,1) == "(" && idx1 > 1 && (idx2 - 5) > idx1 ){ t = t.substr(idx1+1); //console.log("★ 3 Title=" + t); } // Userページ タブタイトルの変更 「DISPNAME (@USERNAME)」→「[@USERNAME]」 idx1 = t.indexOf(' (@'); idx2 = t.indexOf(')'); if( idx1 !== -1 && idx2 !== -1 ) t = '[' + t.substr(idx1+3, idx2-idx1-3) + ']'; // Userページ タブタイトルの変更 「DISPNAME(@USERNAME)さん / X」→「[@USERNAME]」 idx1 = t.indexOf('(@'); idx2 = t.indexOf(')さん'); if( idx1 !== -1 && idx2 !== -1 ) t = '[' + t.substr(idx1+2, idx2-idx1-2) + ']'; } if( document.title != t ){ document.title = t; } } // 個別ツイート表示先頭の「Xユーザーの」を削除 if( (document.title + "").indexOf("Xユーザーの") == 0 ){ document.title = document.title.replace('Xユーザーの',''); } // タブタイトル末尾の 「/ X」を削除 if( (document.title + "").indexOf("\/ X") > -1 ){ document.title = document.title.replace('\/ X',''); } // 検索ページのタイトルが冗長なので省略する if( gi_dispMode == MODE_SEAR && gi_searchPageShortTitle ){ if( (document.title + "").indexOf("検索") > -1 && document.title != "検索" ){ document.title = "検索"; } } //console.log("★ 2 Title=" + document.title); } //「さらに表示」の処理 function execMoreTweet(){ var e2, e3, e4, e5, e6, idx, dt = new Date(); e2 = document.querySelectorAll(HOME_NEW_TWEET); for( idx=0; idx < e2.length; idx++ ){ //遡りスクロール中に出てきた「さらに」表示はモードに関係なくトリガさせる if( ( gi_displayPaused == 1 && window.pageYOffset > window.innerHeight ) || ( ( gi_autoClickNewTweet && (gi_modeAutoOff == 0 || gi_displayPaused == 0) ) && ( window.pageYOffset <= SCROLL_LIMIT || window.pageYOffset > window.innerHeight / 2 ) ) ){ e3 = e2[idx].firstElementChild; if( e3 !== null ){ e4 = e3.firstElementChild; if( e4 !== null ){ e5 = e4.firstElementChild; if( e5 !== null ){ e6 = e5.textContent; if( e6.indexOf("さらに") != -1 || e6.indexOf("More") != -1 || e6.indexOf("more") != -1 ){ //色替え・半自動更新表示 forceUpdateColor(COLOR_UPDATE, TXT_AUTOCLICKMOR); //console.log("★replaceElements1 「さらに」のエレメント発見、トリガ[" + idx + "]"); dispDebugTextWithTime("execMoreTweet : AutoTrigger[1]"); e2[idx].click(); return; } } } } } //自動更新OFFのボタンが押されて有効となっている場合は自動クリックも停止 if( gi_autoClickNewTweet && (gi_modeAutoOff == 0 || gi_displayPaused == 0) && ( window.pageYOffset <= SCROLL_LIMIT || window.pageYOffset > window.innerHeight / 2 ) ) { forceUpdateColor(COLOR_UPDATE, TXT_AUTOCLICKMOR); //console.log("★replaceElements2 新着のエレメントを自動クリック[" + idx + "]"); dispDebugTextWithTime("execMoreTweet : AutoTrigger[2]"); e2[idx].click(); return; } //手動更新直後に新着表示だけされて読み込まれないパターンの救済 if( gi_manualUpdateTriggerNewTweet && (dt.getTime() - gdt_lastTriggerTime.getTime() <= gi_manualUpdateIntervalSec * 1000) ){ forceUpdateColor(COLOR_UPDATE, TXT_AUTOCLICKMOR); //console.log("★replaceElements3 新着のエレメントを自動クリック[" + idx + "]"); dispDebugTextWithTime("execMoreTweet : AutoTrigger[3]"); e2[idx].click(); return; } } } //リストページのスクロール分割下処理 function execListPageSplitScroll(){ //リストページは何故か一定以上スクロールするとヘッダ非表示のCSSが悪さをするらしくDOM更新が止まらなくなるのを抑止 if( gi_dispMode == MODE_LIST ){ var elm; if( window.pageYOffset <= LIST_PAGE_SCROLL_LIMIT ){ elm = document.querySelectorAll('body[' + gstr_scrScrollList +']'); if( elm.length > 0 ){ elm[0].removeAttribute( gstr_scrScrollList ); dispDebugTextWithTime("execListPageSplitScroll : ListScrollLimit RESET=" + Math.floor(window.pageYOffset), LOG_WARN); //console.log("★execListPageSplitScroll: reset gstr_scrScrollList"); } }else{ elm = document.querySelectorAll('body:not([' + gstr_scrScrollList +'])'); if( elm.length > 0 ){ elm[0].setAttribute( gstr_scrScrollList, "" ); dispDebugTextWithTime("execListPageSplitScroll : ListScrollLimit SET=" + Math.floor(window.pageYOffset), LOG_WARN); //console.log("★execListPageSplitScroll: set gstr_scrScrollList"); } } } } /************************************************************ 各種内部処理関数 ************************************************************/ //URLからモードを決定する function getModeFromURL(){ //画面遷移が発生したので動作モードの決定 var hr = window.location.href; if( hr == (TWITTER_URL + PATH_HOME)){ gi_dispMode = MODE_HOME; }else if( hr.indexOf(TWITTER_URL + PATH_LIST) != -1 ){ gi_dispMode = MODE_LIST; }else if( hr.indexOf(TWITTER_URL + PATH_NOTI) != -1 ){ gi_dispMode = MODE_NOTI; }else if( hr.indexOf(TWITTER_URL + PATH_SEAR) != -1 ){ gi_dispMode = MODE_SEAR; }else if(isOtherURL(hr)){ gi_dispMode = MODE_NULL; }else if( hr.indexOf(TWITTER_URL) != -1 ){ //ユーザーアカウント名で終わるURLなので消去法で各種ページを除外していかないと判定が出来ない gi_dispMode = MODE_USER; }else{ gi_dispMode = MODE_NULL; } } //画像サムネイルをクリックで処理をするための下処理 function settingOpenImageNewTab(){ //画像リンクの処理 if( gi_displayImageNewTab ){ //静止画リンクの処理(別タブに元画像サイズで表示) const PHOTO_HREF = '[href$="/photo/1"],[href$="/photo/2"],[href$="/photo/3"],[href$="/photo/4"]'; document.querySelectorAll('a[href*="/status/"][role="link"]:not([' + IMAGE_LINK + ']):is(' + PHOTO_HREF + '):has(img[draggable="true"])').forEach(function(e) { e.setAttribute( IMAGE_LINK, "" ); //console.log("★Image find=" + e.getAttribute('href')); //右クリックでは複数枚一気に開く e.oncontextmenu = function(e){ e.stopPropagation(); var i, h; //1〜3枚の場合は6階層上だが4枚では7階層上を親ノードとして画像が並んでいる var p = getParentElement( e.target, 7 ); if( p === null ) return false; //複数枚のうちクリックされた任意の1枚から親を求めてそこの下にぶら下がっている全部を取得 var elms = p.querySelectorAll('img[draggable="true"]:not([alt="埋め込み動画"])'); //複数貼られている画像をそれぞれ別タブに開く for( i=0; i -1 ){ h = h.substr(0, h.indexOf('?')) + "?format=jpg&name=orig"; } if( i==0 ){ //nameクエリがorigだと開かない画像があるので2回目はlargeで開いてみる if( h == gstr_lastImagePath ){ h = h.replace("orig","large"); gstr_lastImagePath = ""; }else{ gstr_lastImagePath = h; } }else{ if( gstr_lastImagePath == "" ){ h = h.replace("orig","large"); } } }else{ //常に大サイズで開く if( h.indexOf('?') > -1 ){ h = h.substr(0, h.indexOf('?')) + "?format=jpg&name=large"; } gstr_lastImagePath = ""; } window.open( h, '_blank' ); } //RTされた同一の記事が複数表示されないようにする function removeSameArticle(){ if( ! gi_notDispSameArticle ) return; var e0, e1, e2, i, j, u1, u2; //重複の削除 e0 = document.querySelectorAll('div[data-testid="cellInnerDiv"]:has(a[href*="/status/"]):has(span[datetime])'); for(i=e0.length-1; i > -1; i--){ e1 = e0[i].querySelectorAll('a[href*="/status/"]:has(span[datetime])'); if( e1[0] !== null ){ for(j=0; j < i; j++){ e2 = e0[j].querySelectorAll('a[href*="/status/"]:has(span[datetime])'); if( e2[0] !== null ){ u1 = e1[0].getAttribute('href'); u2 = e2[0].getAttribute('href'); //console.log("★ removeSameArticle i=" + i + " : " + u1 + " # j=" + j + " : " + u2 ); if( u1 == u2 && e0[j].getAttribute(gstr_multipleArticleAttr) != "1" ){ //console.log("★removeSameArticle: HIT i=" + i + " / j=" + j + " : " + u2 ); dispDebugTextWithTime("removeSameArticle : " + u1); e0[j].style.display = "none"; e0[j].setAttribute(gstr_multipleArticleAttr, "1"); } } } } } } //ツイート完了の純正ポップアップを捕捉してスクロール戻しとエディット非表示を行う function checkNewTweetComplete(){ var e0, dt = new Date(), find = false; if( dt.getTime() - gobj_newTweetCompleteTime.getTime() < gi_newTweetCompleteHoldTimeMs ){ return; } e0 = document.querySelectorAll('div[id="react-root"] div[id="layers"] span[class="css-1qaijid r-bcqeeo r-qvutc0 r-1tl8opc"]'); //複数出現の可能性あり?一応ループでまわす for( var i=0; i < e0.length; i++ ){ if( (e0[i].innerHTML + "").indexOf("ポストを送信しました。") > -1 ){ find = true; break; } } if( find ){ gobj_newTweetCompleteTime = dt; window.setTimeout( function(){ clearEditControl(); if( dt.getTime() - gobj_editTime.getTime() < EDIT_PAST_TIME ){ dispDebugTextWithTime("checkNewTweetComplete : scroll to top", LOG_OPE); window.scrollTo(0, SCROLL_LIMIT ); } gi_hideEditControl = 1; swichEditColumn(); dispDebugTextWithTime("checkNewTweetComplete : swichEditColumn", LOG_OPE); }, gi_newTweetCompleteWaitMs ); } } /************************************************************ 既読ポイント(既読マーク)関連関数 ************************************************************/ //読み込まれたレコードに対して既読マークの下処理を行う function settingReadPoint(u, h, s1, b){ //u: 処理中タブのURL //h: 処理レコードの個別ツイートURL //s1: 処理レコードのタイムスタンプ //b: 追加先の親オブジェクト var idx, dv, chk; //既読マークの処理 if( gi_enableReadPointCheckBox ){ if( gi_dispMode == MODE_HOME || gi_dispMode == MODE_LIST || gi_dispMode == MODE_USER || gi_dispMode == MODE_SEAR ){ //チェックボックスの下地になるdiv作成 dv = document.createElement("div"); dv.setAttribute(gstr_scrReadPointParentAttr,""); dv.style.display = "flex"; dv.style.marginTop = '0px'; dv.style.marginBottom = '0px'; dv.style.marginLeft = '3px'; dv.style.marginRight = '0px'; dv.style.backgroundColor = COLOR_BORDER; dv.style.borderWidth = "0px"; dv.zIndex = "9"; //既読ポイントのチェックボックス追加 chk = document.createElement("input"); chk.setAttribute("type","checkbox"); chk.setAttribute(gstr_scrReadPointAttr,"false"); //IDなしのエレメントはlintが警告を吐くのでサイクリックのIDを振っておく chk.setAttribute("id","ptd_readpoint" + ("00" + gi_recIdx++).slice(-3)); if( gi_recIdx > 999 ) gi_recIdx = 0; //既読ポイントデータと比較 for( idx=0; idx < gi_readArticles; idx++ ){ if( gstrA_readArticleURL[idx] == h ){ chk.setAttribute(gstr_scrReadPointAttr,'true' + idx); chk.checked = true; //捜索モードで既読マークをカウント if( gi_findMode ){ giA_findMark[idx]++; //console.log("★find mark [" + idx + "] = " + h + " (" + s1 + ")"); } break; } } //通り過ぎ判定のために読み込まれたアーティクルのタイムスタンプを蓄積していく if( gi_findMode ){ gstrA_findModeArticleTimeStamp.push(s1); } chk.setAttribute("href", h); chk.setAttribute(CHK_TIMESTAMP, s1); chk.style.marginTop = "2px"; chk.style.marginBottom = "2px"; chk.style.marginLeft = "2px"; chk.style.marginRight = "2px"; chk.style.opacity = (gi_readCheckedColorMode > -1) ? CHECKBOX_ENABLE_OPACITY : CHECKBOX_DISABLE_OPACITY; chk.onchange = function(e){ e.stopPropagation(); //chgReadPoint と appendNextReadCheck 内では連続した読み書きが行われるので処理前にストレージから読み込む loadStorageData(); //クリックされたチェックボックス起点 chgReadPoint(e.target,0); //後続する複数件にチェック処理 appendNextReadCheck(); //chgReadPoint と appendNextReadCheck 内では連続した読み書きが行われるので処理後にストレージに格納する saveStorageData(); return false; }; chk.oncontextmenu = function(e){ e.stopPropagation(); rclickReadPoint(true, false); return false; }; dv.appendChild(chk); b.appendChild(dv); //先祖要素を探して色替え for( idx = 0; idx < gi_readArticles; idx++ ){ var e1 = document.querySelectorAll('div[data-testid="cellInnerDiv"]:has(input[' + gstr_scrReadPointAttr + '="true' + idx + '"][href="' + h + '"])'); //同一の既読ポイントが振られた記事が複数出てくる可能性があるのでループで処理する for( var j=0; j -1 ){ e1[j].style.backgroundColor = READ_COLOR_ENABLED[idx]; }else{ e1[j].style.backgroundColor = null; } gstrA_readTimeStamp[idx] = s1; gstrA_readArticleURL[idx] = h; } } }else{ //console.log("★ gi_dispMode=" + gi_dispMode + " / " + u ); } } } //既読ポイントの変更 function chgReadPoint(obj, idx){ //obj: クリックされたチェックボックスオブジェクト //idx: 既読ポイント番号 if( ! gi_enableReadPointCheckBox ) return; var c, u, i, j, e0, e1, flg = false; var h = getPageURL(); if( h == "" ) return; if( gi_dispMode == MODE_NOTI ) return; if( obj !== null ){ c = obj.checked; u = obj.getAttribute('href'); //既にチェック済みになっているエレメントを戻す if( idx == 0 ){ e0 = document.querySelectorAll('div[data-testid="cellInnerDiv"]:has(input[' + gstr_scrReadPointAttr + '^="true"])'); for( i = 0; i < e0.length; i++ ){ e0[i].style.backgroundColor = null; e1 = e0[i].querySelectorAll('input[' + gstr_scrReadPointAttr + ']'); //同一の既読ポイントが振られた記事が複数出てくる可能性があるのでループで処理する for( j=0; j -1 ){ e1[i].style.backgroundColor = READ_COLOR_ENABLED[idx]; }else{ e1[i].style.backgroundColor = null; } gstrA_readTimeStamp[idx] = obj.getAttribute(CHK_TIMESTAMP); gstrA_readArticleURL[idx] = u; saveSetting( READ_HEADER[idx], h, u, true, true ); saveSetting( READTM_HEADER[idx], h, gstrA_readTimeStamp[idx], true, true ); } }else{ //チェックが外されたアーティクルを戻しローカル保存データの破棄 obj.checked = false; obj.setAttribute(gstr_scrReadPointAttr,'false'); //チェック数の定義を減らした後にゴミが残らないように最大数まで探して消す for( i=0; i< 100; i++ ){ //定義数が減った時に定義が残るのでクリアする removeSetting( READ_HEADER[i], h, true, true ); removeSetting( READTM_HEADER[i], h, true, true ); if( i < gi_readArticles ){ gstrA_readTimeStamp[i] = ""; gstrA_readArticleURL[i] = ""; } } } } } //既読ポイントの有効無効切り替え function chgReadPointMode(){ if( ! gi_enableReadPointCheckBox ) return; var h = getPageURL(); if( h == "" ) return; if( gi_dispMode == MODE_NOTI ) return; var i, j, e0, e1, idx; //色と透明度を戻す e0 = document.querySelectorAll('div[data-testid="cellInnerDiv"]:has(input[' + gstr_scrReadPointAttr + '^="true"])'); for( i = 0; i < e0.length; i++ ){ e1 = e0[i].querySelectorAll('input[' + gstr_scrReadPointAttr + ']'); //同一の既読ポイントが振られた記事が複数出てくる可能性があるのでループで処理する for( j=0; j < e1.length; j++ ){ idx = Number((e1[j].getAttribute(gstr_scrReadPointAttr) + "").replace("true","")); if( gi_readCheckedColorMode > -1 ){ e0[i].style.backgroundColor = READ_COLOR_ENABLED[idx]; e1[j].style.opacity = CHECKBOX_ENABLE_OPACITY; }else{ e0[i].style.backgroundColor = null; e1[j].style.opacity = CHECKBOX_DISABLE_OPACITY; } } } e0 = document.querySelectorAll('div[data-testid="cellInnerDiv"]:has(input[' + gstr_scrReadPointAttr + '="false"])'); for( i = 0; i < e0.length; i++ ){ e1 = e0[i].querySelectorAll('input[' + gstr_scrReadPointAttr + ']'); //同一の既読ポイントが振られた記事が複数出てくる可能性があるのでループで処理する for( j=0; j < e1.length; j++ ){ e0[i].style.backgroundColor = null; if( gi_readCheckedColorMode > -1 ){ e1[j].style.opacity = CHECKBOX_ENABLE_OPACITY; }else{ e1[j].style.opacity = CHECKBOX_DISABLE_OPACITY; } } } } //非表示指定されているアーティクルではないかどうかを判定 function isNotHiddenArticle(obj){ //obj: 対象のエレメント //return: 全て未設定=true, どれか設定されている=false if( obj !== null && obj.style.display != "none" && obj.clientHeight > 0 && obj.getAttribute(gstr_multipleArticleAttr) != "1" && obj.getAttribute(gstr_scrFixedUserAttr) != "1" && obj.getAttribute(gstr_scrNGAttr) != "1"){ return true; }else{ return false; } } //下層のエレメントが非表示かどうかを判定 function isNotHiddenUnderActile(obj){ //obj: 対象のエレメント //return: 表示状態=true, 非表示状態=false if( obj !== null && obj.style.display != "none" && obj.clientHeight > 0 ){ return true; }else{ return false; } } //既読ポイントの自動設定・更新処理 function updateReadCheckCommon(mode){ //mode: updateReadCheck=0, appendNextReadCheck=1 var e0, e1, e2, e3, e4, e5, idx = 0; e0 = document.querySelectorAll('div[data-testid="cellInnerDiv"]:has(input[' + gstr_scrReadPointAttr + '])'); for( var i=0; i< e0.length; i++ ){ if( isNotHiddenArticle(e0[i]) ){ e1 = e0[i].querySelectorAll('input[' + gstr_scrReadPointAttr + ']'); if( e1.length > 0 ){ e2 = e0[i].firstElementChild; //1階層下・2階層下のエレメントでdisplay=noneになっている場合がある if( isNotHiddenUnderActile(e2) ){ e3 = e2.firstElementChild; if( isNotHiddenUnderActile(e3) ){ if( mode == 0 ){ e1[0].checked = true; //チェック更新処理 chgReadPoint(e1[0] ,idx++); if( idx == gi_readArticles ) return; }else{ //チェックされた本体の特定 if( idx == 0 && e1[0].checked == true ){ idx++; }else if( idx > 0 ){ //チェック更新処理 e1[0].checked = true; chgReadPoint(e1[0] ,idx++); } if( idx == gi_readArticles ) return; } } } } } } } //手動更新時に既読ポイントを現在表示中の最新アーティクルから自動設定する function updateReadCheck(){ updateReadCheckCommon(0); } //既読ポイント設定時に続く数件を自動設定する function appendNextReadCheck(){ updateReadCheckCommon(1); } //既読マーク背景色切り替え function changeReadPointColor(){ if( ! gi_enableReadPointCheckBox ) return; switch( gi_readCheckedColorMode ){ case 0: READ_COLOR_ENABLED = READ_COLOR_ENABLED1; break; case 1: READ_COLOR_ENABLED = READ_COLOR_ENABLED2; break; case 2: READ_COLOR_ENABLED = READ_COLOR_ENABLED3; break; case 3: READ_COLOR_ENABLED = READ_COLOR_ENABLED4; break; } chgReadPointMode(); } //既読ポイント背景色のセットアップ(システムコンフィグ項目のローカルデータ読み込み完了後にメイン関数から呼び出して初期化する) function setupBgColorTables(){ if( ! READ_COLOR_CYCLEMODE ){ //既読ポイント背景色パターン以降がある場合 パターン以降先頭要素で繰り返し for( gi_defIdx=gi_readColorPattern; gi_defIdx < gi_readArticles; gi_defIdx++ ){ READ_COLOR_ENABLED1[gi_defIdx] = DEF_READ_COLOR_ENABLED1; READ_COLOR_ENABLED2[gi_defIdx] = DEF_READ_COLOR_ENABLED2; READ_COLOR_ENABLED3[gi_defIdx] = DEF_READ_COLOR_ENABLED3; READ_COLOR_ENABLED4[gi_defIdx] = DEF_READ_COLOR_ENABLED3; } }else{ //既読ポイント背景色パターン以降がある場合 パターン全体を繰り返す for( gi_defIdx=gi_readColorPattern; gi_defIdx < gi_readArticles; gi_defIdx++ ){ READ_COLOR_ENABLED1[gi_defIdx] = READ_COLOR_ENABLED1[gi_defIdx % gi_readColorPattern]; READ_COLOR_ENABLED2[gi_defIdx] = READ_COLOR_ENABLED2[gi_defIdx % gi_readColorPattern]; READ_COLOR_ENABLED3[gi_defIdx] = READ_COLOR_ENABLED3[gi_defIdx % gi_readColorPattern]; READ_COLOR_ENABLED4[gi_defIdx] = READ_COLOR_ENABLED4[gi_defIdx % gi_readColorPattern]; } } } //既読マーク背景色設定の読込 function loadReadPointColorSetting(){ if( ! gi_enableReadPointCheckBox ) return; var u = getPageURL(); if( u == "" ) return; gi_readCheckedColorMode = Number(loadSetting(CHKCOLOR_HEADER, u)); changeReadPointColor(); } //既読ポイントチェックボックスの右クリック function rclickReadPoint(doCycle, notDispMsg){ //doCycle: true=表示タイプの順次切り替えモード / false=コンフィグからの変更モード //notDispMsg: true=ポップアップメッセージなし / false=ポップアップメッセージあり if( ! gi_enableReadPointCheckBox ) return; var u = getPageURL(); if( u == "" ) return; var i, j, e0; if( doCycle ){ //表示色の入れ替え if( ++gi_readCheckedColorMode >= READ_COLOR_CYCLE ) gi_readCheckedColorMode = -1; saveSetting(CHKCOLOR_HEADER, u, gi_readCheckedColorMode); } changeReadPointColor(); if( gi_readCheckedColorMode > -1 ){ forceUpdateColor(COLOR_FGCOLOR, TXT_CHANGEBGTYPE.replace("#", Number(gi_readCheckedColorMode + 1))); for( i = 0; i < gi_readArticles; i++ ){ e0 = document.querySelectorAll('div[data-testid="cellInnerDiv"]:has(input[' + gstr_scrReadPointAttr + '="true' + i + '"])'); //同一の既読ポイントが振られた記事が複数出てくる可能性があるのでループで処理する for( j=0; j < e0.length; j++ ){ e0[j].style.backgroundColor = READ_COLOR_ENABLED[i]; } } if( ! notDispMsg ){ dispPopupMessage("既読マークの背景色をType" + (gi_readCheckedColorMode+1) + "に変更しました", gi_displayPopupCloseTimeSec); } }else{ forceUpdateColor(COLOR_FGCOLOR, TXT_CHANGEBGNONE); for( i = 0; i < gi_readArticles; i++ ){ e0 = document.querySelectorAll('div[data-testid="cellInnerDiv"]:has(input[' + gstr_scrReadPointAttr + '="true' + i + '"])'); //同一の既読ポイントが振られた記事が複数出てくる可能性があるのでループで処理する for( j=0; j < e0.length; j++ ){ e0[j].style.backgroundColor = null; } } if( ! notDispMsg ){ dispPopupMessage("既読マークを非表示に変更しました", gi_displayPopupCloseTimeSec); } } } /************************************************************ 新着の積み上げ更新関連関数 ************************************************************/ const CHECKBOX_ADDED_COLUMN = 'div[data-testid="cellInnerDiv"]:has(span[datetime],time[datetime])'; const CHECKBOX_ADDED_COLUMN_HREF = 'a[href]:has(span[datetime],time[datetime])'; //更新トリガ前の状態を保存する function clickNewestTweetPreSave(){ gstrA_beforeContArticles = []; giA_beforeContArticlesOffset = []; var e0, e1, e2, e3, e4, e5, h, rect; e0 = document.querySelectorAll(CHECKBOX_ADDED_COLUMN); for( var i=0; i< e0.length; i++ ){ if( isNotHiddenArticle(e0[i]) ){ e1 = e0[i].querySelectorAll(CHECKBOX_ADDED_COLUMN_HREF); if( e1.length > 0 ){ e2 = e0[i].firstElementChild; //1階層下・2階層下のエレメントでdisplay=noneになっている場合がある if( isNotHiddenUnderActile(e2) ){ e3 = e2.firstElementChild; if( isNotHiddenUnderActile(e3) ){ //有効アーティクルの記録を行う h = e1[0].getAttribute('href') + ""; h = h.replace(TWITTER_URL,""); if( h != "" ){ gstrA_beforeContArticles.push(h); rect = e1[0].getBoundingClientRect(); giA_beforeContArticlesOffset.push(Math.floor(rect.top)); } } } } } } } //更新トリガ直後に現時点の最新アーティクルに遷移する function clickNewestTweetStart(count){ //count: 再試行回数 var e0, e1, e2, e3, e4, e5, h, rect; if( gi_continuousMode == 0 || gi_continuousPhase < 0 ) return; //新着積み上げモード開始 if( count == 0 ){ gi_updateContinuousReturnRetry = 0; dispDebugTextWithTime("Cont1 : Start Continuous Mode", LOG_TRC); gi_continuousPhase = CONT_START1; }else{ dispDebugTextWithTime("Cont1 : Start Continuous Mode Retry[" + count + "]", LOG_WARN); } e0 = document.querySelectorAll(CHECKBOX_ADDED_COLUMN); for( var i=0; i< e0.length; i++ ){ if( isNotHiddenArticle(e0[i]) ){ e1 = e0[i].querySelectorAll(CHECKBOX_ADDED_COLUMN_HREF); if( e1.length > 0 ){ e2 = e0[i].firstElementChild; //1階層下・2階層下のエレメントでdisplay=noneになっている場合がある if( isNotHiddenUnderActile(e2) ){ e3 = e2.firstElementChild; if( isNotHiddenUnderActile(e3) ){ //先頭に遷移 if( gi_updateContinuousDispPopup ){ closePopupContinuousMove(); gelm_fixedPopupContinuousMove = dispPopupMessage("先頭記事に一旦遷移します", -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT); } dispDebugTextWithTime("Cont1 : Start Continuous Mode → Move to newest article", LOG_TRC); e1[0].click(); window.setTimeout( clickNewestTweetReturn, gi_updateContinuousReturnTimeMs ); gi_updateContinuousReturnRetry = 0; gi_continuousPhase = CONT_START2; return; } } } } } //遷移先の先頭記事要素が見つからないエラーパターン gi_updateContinuousReturnRetry++; if( gi_updateContinuousReturnRetry < MAX_UPDATE_CONTINUOUS_RETURN_RETRY ){ window.setTimeout( clickNewestTweetStart, gi_updateContinuousReturnTimeMs, ++count ); if( gi_updateContinuousDispPopup ){ closePopupContinuousMove(); gelm_fixedPopupContinuousMove = dispPopupMessage("先頭記事に一旦遷移します 待ち合わせ" + gi_updateContinuousReturnRetry + "回目", -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT); } }else{ //エラーパターンではポップアップなしの設定でも表示する dispPopupMessage("リトライオーバーしました 手動で元の画面に戻って下さい", gi_displayPopupCloseTimeSec * 3); clickNewestTweetFinish(-1); } } //更新直後に遷移した先から戻る function clickNewestTweetReturn(count=0){ //count: 再試行回数 if( gi_continuousMode == 0 || gi_continuousPhase < 0 ) return; var e0 = document.querySelectorAll('div[aria-label="ホームタイムライン"] div[aria-label="戻る"][role="button"]'); if( e0.length > 0 ){ if( gi_updateContinuousDispPopup ){ window.setTimeout( closePopupContinuousMove, CLOSE_CONTINUOUS_DELAY ); closePopupContinuousReturn(); gelm_fixedPopupContinuousReturn = dispPopupMessage("元の画面に戻ります", -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT); } dispDebugTextWithTime("Cont2 : Return Continuous Mode → Move to timeline[" + count + "]", LOG_TRC); window.setTimeout( clickNewestTweetFinish, gi_updateContinuousResultTimeMs, 0 ); e0[0].click(); gi_updateContinuousReturnRetry = 0; gi_continuousPhase = CONT_RETURN; return; } //戻るボタン要素が見つからないエラーパターン gi_updateContinuousReturnRetry++; if( gi_updateContinuousReturnRetry < MAX_UPDATE_CONTINUOUS_RETURN_RETRY ){ window.setTimeout( clickNewestTweetReturn, gi_updateContinuousReturnTimeMs ); if( gi_updateContinuousDispPopup ){ window.setTimeout( closePopupContinuousMove, CLOSE_CONTINUOUS_DELAY ); closePopupContinuousReturn(); gelm_fixedPopupContinuousReturn = dispPopupMessage("元の画面に戻ります 待ち合わせ" + gi_updateContinuousReturnRetry + "回目", -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT); } }else{ //エラーパターンではポップアップなしの設定でも表示する dispPopupMessage("リトライオーバーしました 手動で元の画面に戻って下さい", gi_displayPopupCloseTimeSec * 3); clickNewestTweetFinish(-2); } } //DOM更新〜レコード更新から一定時間経過するまで待ち合わせ function clickNewestTweetWaiting(){ gf_continuousDOMWaiting = false; if( gi_continuousPhase < 0 ) return; dispDebugTextWithTime("clickNewestTweetWaiting : phase=" + CONT_DOMWAIT); if( gi_updateContinuousDispPopup ){ window.setTimeout( closePopupContinuousWaitLoop, CLOSE_CONTINUOUS_DELAY ); closePopupContinuousFinish(); gelm_fixedPopupContinuousFinish = dispPopupMessage("新着積み上げ更新の完了判定中", -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT); } gi_continuousPhase = CONT_DOMWAIT; } //タイムラインに戻ってきたあとの判定処理 function clickNewestTweetFinish(count){ //count: 呼び出し回数0〜 , =-1:開始処理でリトライオーバー , =-2:復帰処理でリトライオーバー var e0, e1, e2, e3, e4, e5, i, j, h, rect; var find = false, findnew = false, minus = false, cont = false; var afterContArticles = [], topPosition = []; if( gi_continuousMode == 0 || gi_continuousPhase < 0 || gi_continuousPhase == CONT_FINISH ) return; dispDebugTextWithTime("Cont3 : count = " + count, LOG_TRC); if( count > -1 ){ //更新されたレコードの取得と判定 e0 = document.querySelectorAll(CHECKBOX_ADDED_COLUMN); for( i=0; i< e0.length; i++ ){ if( isNotHiddenArticle(e0[i]) ){ e1 = e0[i].querySelectorAll(CHECKBOX_ADDED_COLUMN_HREF); if( e1.length > 0 ){ e2 = e0[i].firstElementChild; //1階層下・2階層下のエレメントでdisplay=noneになっている場合がある if( isNotHiddenUnderActile(e2) ){ e3 = e2.firstElementChild; if( isNotHiddenUnderActile(e3) ){ h = e1[0].getAttribute('href') + ""; h = h.replace(TWITTER_URL,""); if( h != "" ){ rect = e1[0].getBoundingClientRect(); topPosition.push(Math.floor(rect.top)); afterContArticles.push(h); } } } } } } //DEBUG for( i=0; i SCROLL_LIMIT ){ startModeScrTopMark(false); } } }else if( findnew && ! minus ){ if( ! gf_continuousDOMWaiting || gi_DOMEventRecvCount > 0 ){ dispDebugTextWithTime("clickNewestTweetFinish : Complete2 : " + count + "[" + gf_continuousDOMWaiting + "/" + gi_DOMEventRecvCount + "]", LOG_ERR); gf_continuousDOMWaiting = false; if( gi_updateContinuousDispPopup ){ closePopupContinuousEnd(); window.setTimeout( closePopupContinuousFinish, CLOSE_CONTINUOUS_DELAY ); gelm_fixedPopupContinuousEnd = dispPopupMessage("新着更新しましたが上には積み上がりませんでした", -1); } gi_continuousPhase = CONT_FINISH; }else{ dispDebugTextWithTime("clickNewestTweetFinish : Continue2 : " + count); cont = true; } }else if( find ){ if( ! gf_continuousDOMWaiting || gi_DOMEventRecvCount > 1 ){ dispDebugTextWithTime("clickNewestTweetFinish : Complete3 : " + count + "[" + gf_continuousDOMWaiting + "/" + gi_DOMEventRecvCount + "]"); gf_continuousDOMWaiting = false; if( gi_updateContinuousDispPopup ){ closePopupContinuousEnd(); window.setTimeout( closePopupContinuousFinish, CLOSE_CONTINUOUS_DELAY ); gelm_fixedPopupContinuousEnd = dispPopupMessage("新着はありませんでした", -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT); } gi_continuousPhase = CONT_FINISH; }else{ dispDebugTextWithTime("clickNewestTweetFinish : Continue3 : " + count); cont = true; } }else{ if( ! gf_continuousDOMWaiting || gi_DOMEventRecvCount > 2 ){ dispDebugTextWithTime("clickNewestTweetFinish : Error End : " + count + "[" + gf_continuousDOMWaiting + "/" + gi_DOMEventRecvCount + "]", LOG_ERR); gf_continuousDOMWaiting = false; //エラーパターンはポップアップ表示設定がOFFでも表示する closePopupContinuousEnd(); window.setTimeout( closePopupContinuousFinish, CLOSE_CONTINUOUS_DELAY ); gelm_fixedPopupContinuousEnd = dispPopupMessage("[遷移タイミングエラー]
新着積み上げ更新は正常に動作しませんでした", -1); gi_continuousPhase = CONT_FINISH; }else{ dispDebugTextWithTime("clickNewestTweetFinish : Continue4 : " + count); cont = true; } } if( cont ){ //待機継続 window.setTimeout( clickNewestTweetFinish, gi_updateContinuousResultTimeMs, ++count ); if( gi_idleShortTimer && gtmr_shortTimer === null ){ replaceElementsOneShot(); } dispDebugTextWithTime("clickNewestTweetFinish : Waiting DOM : " + count); if( gi_updateContinuousDispPopup ){ closePopupContinuousWaitLoop(); window.setTimeout( closePopupContinuousWaitStart, 500 ); gelm_fixedPopupContinuousWaitLoop = dispPopupMessage("新着積み上げの更新データの受信完了待ち[" + count + "]", -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT); } gi_continuousPhase = CONT_WAITCONT; return; } }else{ dispDebugTextWithTime("clickNewestTweetFinish : Retry Error : " + count, LOG_ERR); gi_continuousPhase = CONT_RETRYERROR; } //動いているタイマを終了させる if( gtmr_waitContinuous !== null ){ window.clearTimeout(gtmr_waitContinuous); gtmr_waitContinuous = null; } if( gtmr_timeoutContinuous !== null ){ window.clearTimeout(gtmr_timeoutContinuous); gtmr_timeoutContinuous = null; } resetContinuousParams(); window.setTimeout( function(){ closePopupContinuousAll(); gi_continuousPhase = CONT_IDLE; }, gi_displayPopupCloseTimeSec * 1000 ); } //タイムアウトエラー function clickNewestTweetTimeout(flg){ //flg: true=タイムアウト false=中断 if( gi_continuousPhase >= CONT_FINISH ) return; if( gtmr_waitContinuous !== null ){ window.clearTimeout(gtmr_waitContinuous); gtmr_waitContinuous = null; } if( gtmr_timeoutContinuous !== null ){ window.clearTimeout(gtmr_timeoutContinuous); gtmr_timeoutContinuous = null; } if( flg ){ gi_continuousPhase = CONT_TIMEOUT; dispDebugTextWithTime("clickNewestTweetTimeout : Error End ", LOG_ERR); //エラーパターンはポップアップ表示設定がOFFでも表示する closePopupContinuousEnd(); gelm_fixedPopupContinuousEnd = dispPopupMessage("[レコード更新タイムアウト]
新着積み上げ更新は正常に動作しませんでした", -1); //画面遷移時の初期処理に失敗している可能性が高いので再初期化する resetElements(); }else{ gi_continuousPhase = CONT_ABORT; dispDebugTextWithTime("clickNewestTweetTimeout : Abort "); if( gi_updateContinuousDispPopup ){ closePopupContinuousEnd(); gelm_fixedPopupContinuousEnd = dispPopupMessage("新着積み上げ更新が中断されました", -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_CONT); } } window.setTimeout( function(){ closePopupContinuousAll(); gi_continuousPhase = CONT_IDLE; }, gi_displayPopupCloseTimeSec * 1000 ); resetContinuousParams(); } //新着積み上げに用いる各種変数を初期化 function resetContinuousParams(){ gi_continuousMode = 0; gf_continuousDOMWaiting = false; gf_DOMEventRecv = false; gi_DOMEventRecvCount = 0; gi_updateContinuousReturnRetry = 0; gstrA_beforeContArticles = []; giA_beforeContArticlesOffset = []; } /************************************************************ 既読ポイント捜索モード関連関数 ************************************************************/ //既読ポイントを遡って探す function startReadPointFindingMode(){ var i, j, h, c=0, v, findIdx=-1, e, e0, e1, e2, e3, e4, e5, w1, idx = 0, msg = "", aliveReadPoint = 0; if( ! gi_enableReadPointCheckBox ) return; //既に動いていたら停止 if( gi_findMode ){ resetFindModeParams(); if( gi_findModeDispPopup ){ dispPopupMessage("既読ポイント捜索を停止しました" , gi_displayPopupCloseTimeSec * 3, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND); } closePopupFindAll(); return; } //対象外ページでは処理しない if( gi_dispMode != MODE_HOME && gi_dispMode != MODE_LIST && gi_dispMode != MODE_USER && gi_dispMode != MODE_SEAR ) return; //生きている既読ポイントの数 for( i=0; i[" + toFormatedDateString(new Date()) + "]
既読ポイントの捜索を開始します
"; msg += "(" + BTN_TXT_BTNL + "," + BTN_TXT_BTNM + "," + BTN_TXT_BTNR + "や右のボタンで中断)"; msg += "
"; msg += ""; gelm_fixedPopupFindConfirm = dispPopupMessage( msg, -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND, true, false); dispDebugTextWithTime("既読ポイントの捜索を開始します/BTNで中断", LOG_DIAG); e = document.getElementById('ELM_FINDMODE_BTN1'); if( e !== null ){ e.onclick = function(){ resetFindModeParams(); if( gi_findModeDispPopup ){ dispPopupMessage("既読ポイント捜索を停止しました" , gi_displayPopupCloseTimeSec * 3, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND); } closePopupFindAll(); }; } //短周期処理のワンショット実行 replaceElementsOneShot(); //継続動作へ移行 window.setTimeout( continueReadPointFindingMode, gi_findModeIntervalMs ); } //既読ポイントを遡って探す(継続動作中) function continueReadPointFindingMode(){ //解除されたら停止 if( ! gi_findMode ){ gi_findReadPointCount = 0; return; } var i, e0, e1, e2, e3, h, findCount = 0, idx = -1, msg = ""; var t0 = [], t1 = [], flg = false, aliveReadPoint = 0; //既読マークのタイムスタンプを降順に並ぶものだけ抽出したもの var gstrA_sortedMarkTimeStamp = []; //読み込まれた全アーティクルのタイムスタンプを降順に並ぶものだけ抽出したもの var gstrA_sortedAllTimeStamp = []; for( i=0; i < gi_readArticles; i++ ){ if( giA_findMark[i] > 0 ){ if( findCount == 0 ){ //見つけた先頭マーク要素のインデックス idx = i; } findCount++; } } //生きている既読ポイントの数 for( i=0; i gi_findReadPointCount ){ closePopupFindCount(); if( gi_findModeDispPopup ){ gelm_fixedPopupFindCount = dispPopupMessage("既読ポイントを " + findCount + " / " + aliveReadPoint + " 個発見しました" , -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND); } gi_findReadPointCount = findCount; } //有効な既読ポイントから消失予想分を引いた数まで見つかったら終了 if( (aliveReadPoint - FIND_READ_COUNTSUB <= findCount) || (aliveReadPoint >= FIND_READ_THRETHOLD && Math.floor(FIND_READ_THRETHOLD * FIND_READ_RATIO) <= findCount) ){ if( gi_findModeDispPopup ){ window.setTimeout( function(){if(gi_findModeDispPopup) closePopupFindAll();}, gi_displayPopupCloseTimeSec * 2 ); dispPopupMessage("既読ポイントを " + findCount + " 個発見したので捜索を終了します" , gi_displayPopupCloseTimeSec * 3, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND); }else{ closePopupFindAll(); } resetFindModeParams(); if( idx > -1 ){ for( i=idx; i < gi_readArticles; i++ ){ if( giA_findMark[i] > 0 ){ e0 = document.querySelectorAll('div[data-testid="cellInnerDiv"]:has(input[' + gstr_scrReadPointAttr + '="true' + i + '"])'); if( e0.length > 0 ){ //既読マーク一番上のアーティクルが下端に表示される位置までスクロールする e0[0].scrollIntoView({behavior:'smooth',block:'end',inline:'center'}); dispDebugTextWithTime("continueReadPointFindingMode : End scrollIntoView idx=[" + i + "]"); return; } } } } return; } //通り過ぎていないかチェックする 既読マーク配列 t0 = []; gstrA_sortedMarkTimeStamp = []; for( i=gstrA_readTimeStamp.length-1; i>-1; i-- ){ if( gstrA_readTimeStamp[i] != "" && gstrA_readTimeStamp[i] != undefined ){ t0.push(gstrA_readTimeStamp[i]); //console.log("★continueReadPointFindingMode() t0[" + i + "] = " + gstrA_readTimeStamp[i]); } } quicksort(t0); for( i=t0.length-1; i>-1; i-- ){ gstrA_sortedMarkTimeStamp.push(t0[i]); //console.log("★continueReadPointFindingMode() gstrA_sortedMarkTimeStamp[" + i + "] = " + t0[i]); } //var idxMark = Math.floor(gstrA_sortedMarkTimeStamp.length / 2); //console.log("★continueReadPointFindingMode() MAX gstrA_sortedMarkTimeStamp[" + 0 + "] = " + gstrA_sortedMarkTimeStamp[0]); //console.log("★continueReadPointFindingMode() MED gstrA_sortedMarkTimeStamp[" + idxMark + "] = " + gstrA_sortedMarkTimeStamp[idxMark]); //console.log("★continueReadPointFindingMode() MIN gstrA_sortedMarkTimeStamp[" + (gstrA_sortedMarkTimeStamp.length-1) + "] = " + gstrA_sortedMarkTimeStamp[gstrA_sortedMarkTimeStamp.length-1]); //通り過ぎていないかチェックする 全件配列 t0 = []; idx = 0; gstrA_sortedAllTimeStamp = []; for( i=gstrA_findModeArticleTimeStamp.length-1; i>-1; i-- ){ if( gstrA_findModeArticleTimeStamp[i] != "" && gstrA_findModeArticleTimeStamp[i] != undefined ){ t0.push(gstrA_findModeArticleTimeStamp[i]); //console.log("★continueReadPointFindingMode() t0[" + i + "] = " + gstrA_findModeArticleTimeStamp[i]); //取得した最新アーティクルから先頭n件のレコードを抽出 if( ++idx >= FIND_OLD_ARTICLE_COUNT ) break; } } quicksort(t0); for( i=t0.length-1; i>-1; i-- ){ gstrA_sortedAllTimeStamp.push(t0[i]); //console.log("★continueReadPointFindingMode() gstrA_sortedAllTimeStamp[" + i + "] = " + t0[i]); } //var idxAll = Math.floor(gstrA_sortedAllTimeStamp.length / 2); //console.log("★continueReadPointFindingMode() MAX gstrA_sortedAllTimeStamp[" + 0 + "] = " + gstrA_sortedAllTimeStamp[0]); //console.log("★continueReadPointFindingMode() MED gstrA_sortedAllTimeStamp[" + idxAll + "] = " + gstrA_sortedAllTimeStamp[idxAll]); //console.log("★continueReadPointFindingMode() MIN gstrA_sortedAllTimeStamp[" + (gstrA_sortedAllTimeStamp.length-1) + "] = " + gstrA_sortedAllTimeStamp[gstrA_sortedAllTimeStamp.length-1]); if( gi_findModeDispPopup ){ if( gi_findNoTimeStamp ){ msg += " (※時刻比較判定無効)"; } msg += "
既読=" + gstrA_sortedMarkTimeStamp[0] + " / 読込=" + gstrA_sortedAllTimeStamp[0]; msg += "
読み込まれた過去データ件数=" + (gstrA_findModeArticleTimeStamp.length -1); //途中経過情報の表示なので既に出ている情報ダイアログを閉じる closePopupFindInfo(); gelm_fixedPopupFindInfo = dispPopupMessage("発見既読ポイント[" + findCount + " / " + aliveReadPoint + "]" + msg , -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND); } //既読ポイントのタイムスタンプよりも古いものが現れ始めたら行きすぎている if( ! gi_findNoTimeStamp && gstrA_sortedMarkTimeStamp[0] > gstrA_sortedAllTimeStamp[0] ){ //ポップアップ型confirmは完了復帰ではないのでそれぞれボタンのイベントで後続処理を行う closePopupFindContinue(); dispDebugTextWithTime("既読ポイントのタイムスタンプより古いアーティクルに到達しました/中断しますか?", LOG_DIAG); gelm_fixedPopupFindContinue = popupConfirm( "既読ポイントのタイムスタンプより
古いアーティクルに到達しました
中断しますか?", "中断する", function(){ closePopupFindContinue(); if( gi_findModeDispPopup ){ window.setTimeout( function(){closePopupFindAll();}, gi_displayPopupCloseTimeSec * 2 ); dispPopupMessage("既読ポイントのタイムスタンプより古いアーティクルに到達したので捜索を終了します" , gi_displayPopupCloseTimeSec * 3, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND); }else{ closePopupFindAll(); } resetFindModeParams(); }, "続行する", function(){ gi_findNoTimeStamp = 1; closePopupFindContinue(); if( gi_findModeDispPopup ){ dispPopupMessage("タイムスタンプ判定なしで遡ります" , gi_displayPopupCloseTimeSec, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND); } window.setTimeout( continueReadPointFindingMode, gi_findModeIntervalMs ); } ); return; } //読み込まれた件数が一定を超えたら行きすぎている if( gstrA_findModeArticleTimeStamp.length > MAX_CONTINUE_ARTICLES ){ if( gi_findModeDispPopup ){ window.setTimeout( function(){closePopupFindAll();}, gi_displayPopupCloseTimeSec * 2 ); dispPopupMessage(MAX_CONTINUE_ARTICLES + "件遡っても見つからないので捜索を終了します" , gi_displayPopupCloseTimeSec * 3, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND); }else{ closePopupFindAll(); } resetFindModeParams(); return; } //読み込まれている最後のアーティクルを探す e0 = document.querySelectorAll(CHECKBOX_ADDED_COLUMN); for( i=e0.length-1; i>-1; i-- ){ if( isNotHiddenArticle(e0[i]) ){ e1 = e0[i].querySelectorAll(CHECKBOX_ADDED_COLUMN_HREF); if( e1.length > 0 ){ e2 = e0[i].firstElementChild; //1階層下・2階層下のエレメントでdisplay=noneになっている場合がある if( isNotHiddenUnderActile(e2) ){ e3 = e2.firstElementChild; if( isNotHiddenUnderActile(e3) ){ //読み込まれたアーティクル数が増えていないようなら更にスクロールさせる if( gi_lastFindModeArticleRecs == gstrA_findModeArticleTimeStamp.length ){ //何度も続けて件数が増えていない状態になったら中断する if( MAX_FINDMODEARTICLERECSSAMECOUNT < ++gi_lastFindModeArticleRecsSameCount ){ dispDebugTextWithTime("continueReadPointFindingMode : wait over", LOG_ERR ); closePopupFindContinue(); if( gi_findModeDispPopup ){ window.setTimeout( function(){closePopupFindAll();}, gi_displayPopupCloseTimeSec * 2 ); dispPopupMessage("スクロール操作によって過去アーティクルが取得できません" , gi_displayPopupCloseTimeSec * 3, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND); }else{ closePopupFindAll(); } resetFindModeParams(); return; } //短周期処理をワンショット replaceElementsOneShot(); dispDebugTextWithTime("continueReadPointFindingMode : scrollIntoView[A]" ); //読み込まれた最古アーティクルが下端に表示される位置までスクロールする e0[i].scrollIntoView({behavior:'smooth',block:'end',inline:'center'}); }else{ dispDebugTextWithTime("continueReadPointFindingMode : Non-scroll wait[A]"); gi_lastFindModeArticleRecsSameCount = 0; } //読み込まれた前回アーティクル数を保存 gi_lastFindModeArticleRecs = gstrA_findModeArticleTimeStamp.length; window.setTimeout( continueReadPointFindingMode, gi_findModeIntervalMs ); return; } } } } } //読み込まれたアーティクル数が増えていないようなら更にスクロールさせる if( gi_lastFindModeArticleRecs == gstrA_findModeArticleTimeStamp.length){ dispDebugTextWithTime("continueReadPointFindingMode : scrollTo " + (window.pageYOffset + window.innerHeight) + "[B]", LOG_WARN ); window.scrollTo(0, window.pageYOffset + window.innerHeight); }else{ dispDebugTextWithTime("continueReadPointFindingMode : Non-scroll wait[B]", LOG_WARN); } //読み込まれた前回アーティクル数を保存 gi_lastFindModeArticleRecs = gstrA_findModeArticleTimeStamp.length; window.setTimeout( continueReadPointFindingMode, gi_findModeIntervalMs ); } //捜索モードに使うパラーメータ類を初期化 function resetFindModeParams(){ gi_findMode = 0; gi_findNoTimeStamp = 0; gi_findReadPointCount = 0; gi_lastFindModeArticleRecs = 0; gi_lastFindModeArticleRecsSameCount = 0; gstrA_findModeArticleTimeStamp = []; //終了処理時にワンショット実行 if( gi_idleShortTimer && gtmr_shortTimer === null ){ replaceElementsOneShot(); } } /************************************************************ 次回スクロール位置が先頭に戻ったら既読マークする関連関数 ************************************************************/ //スクロールイベント function funcScrollEvent(){ var oneShot = false; //先頭でマークするモードの動作中 if( gi_flgScrTopMarkMode ){ //途中で他の画面に遷移された場合は処理しない if( gstr_flgScrToTopURL != window.location.href ){ gf_flgScrTopMarkReturn = true; //console.log("★funcScrollEvent MovedURL : " + location.href); return; } //遷移先から戻ってきた初回のみ処理しない if( gf_flgScrTopMarkReturn ){ gf_flgScrTopMarkReturn = false; //console.log("★funcScrollEvent ReturnURL : " + location.href); return; } if( window.pageYOffset == 0 ){ //捜索中のスクロールイベントは無視 if( gi_findMode ) return; //連続更新前にストレージから読み出す loadStorageData(); //マークを先頭記事から更新 updateReadCheck(); //連続更新後にストレージに格納する saveStorageData(); //終了 window.setTimeout( endModeScrTopMark, 10 ); dispDebugTextWithTime("funcScrollEvent : ScrTopMark Complete", LOG_OPE ); //console.log("★funcScrollEvent : " + location.href); }else{ if( gi_useScrollEvent ){ oneShot = true; } } }else{ //常時スクロールイベントで短周期動作をコントロールするモード if( gi_useScrollEvent ){ //スクロールによるトリガの時 if( gi_execTriggerByScroll ){ dispDebugTextWithTime("funcScrollEvent : return scroll=" + Math.floor(window.pageYOffset) ); gi_execTriggerByScroll = 0; return; } oneShot = true; } //リストページの分割スクロール処理 execListPageSplitScroll(); } if( oneShot ){ //短周期処理のワンショット実施 replaceElementsOneShot(); dispDebugTextWithTime("funcScrollEvent : replaceElementsOneShot scroll=" + Math.floor(window.pageYOffset), LOG_TRC ); } } //スクロール位置が先頭に戻ったら既読マークをする動作の開始 function startModeScrTopMark(withFindMode){ //withFindMode: true=既読マーク捜索と併せて使う / false:単独で実行 var msg = ""; //単独実行 if( window.pageYOffset <= SCROLL_LIMIT && ! withFindMode ) return; if( gi_flgScrTopMarkMode || gelm_fixedScrTopMark !== null ){ endModeScrTopMark(); } if( gi_scrTopMarkModeDispPopup ){ var w1 = getDialogWidth(); //スクロール位置が先頭に戻ったら既読マークをする処理中のポップアップ表示 msg += "
[" + toFormatedDateString(new Date()) + "]
先頭に戻ると既読マークします
"; msg += "
"; msg += "
"; closePopupScrTopMark(); gelm_fixedScrTopMark = dispPopupMessage(msg, -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_TOPM, true, false); var e = document.getElementById('ELM_SCRTOTOP_BTN1'); if( e !== null ){ e.onclick = function(){ dispPopupMessage("先頭で既読マークのモードを解除しました" , gi_displayPopupCloseTimeSec, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_TOPM); window.setTimeout( endModeScrTopMark, 10 ); }; } } //モード開始 gi_flgScrTopMarkMode = 1; gstr_flgScrToTopURL = window.location.href; gf_flgScrTopMarkReturn = false; dispDebugTextWithTime("startModeScrTopMark : Start mode=" + withFindMode, LOG_OPE ); } //スクロール位置が先頭に戻ったら既読マークする処理の終了 function endModeScrTopMark(){ //ポップアップ消去 if( gi_scrTopMarkModeDispPopup ){ closePopupScrTopMark(); } //モード終了 gi_flgScrTopMarkMode = 0; gstr_flgScrToTopURL = ""; gf_flgScrTopMarkReturn = false; //終了時にワンショット実行 if( gi_idleShortTimer && gtmr_shortTimer === null ){ replaceElementsOneShot(); } } /************************************************************ 通知ページ関連関数 ************************************************************/ const NEW_NOTI_CONTROL_ELEMENT = 'div[aria-label="ホームタイムライン"] > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1)'; const NEW_NOTI_NEWMARK_ELEMENT = 'nav[aria-label="メインメニュー"] a[aria-label^="通知("][aria-label$="件の未読通知)"]'; const NEW_NOTI_DM_ELEMENT = 'nav[aria-label="メインメニュー"] a[aria-label^="ダイレクトメッセージ("][aria-label$="件の未読会話)"]'; //通知ページの新着表示を戻す function clearNewNotification(){ if( gtmr_waitClear !== null ) return; //gelm_fixedPopupClearNewTweetが生きていてgf_flgClearNotification==trueになるスレ違いパターンがある if( gf_flgClearNotification && gelm_fixedPopupClearNewTweet === null ) return; //上部を詰めている要素と通知新着要素の確認 var e0 = document.querySelectorAll(NEW_NOTI_CONTROL_ELEMENT); if( e0.length > 0 ){ var e1 = document.querySelectorAll(NEW_NOTI_NEWMARK_ELEMENT); if( e1.length > 0 ){ var he = e0[0].clientHeight; if( he < 50 ){ e0[0].style.height = "100px"; gf_flgClearNotification = true; gtmr_waitClear = window.setTimeout( waitforNotificationClear, 1000 ); closePopupClearNewTweetMessage(); gelm_fixedPopupClearNewTweet = dispPopupMessage("新着通知の表示から戻します", CLEAR_NEWNOTI_SEC); } } } } //新着件数表示が無くなるまで待つ function waitforNotificationClear(){ //多重で走らないようにタイマキャンセル if( gtmr_waitClear !== null ){ window.clearTimeout(gtmr_waitClear); gtmr_waitClear = null; } var e0 = document.querySelectorAll(NEW_NOTI_CONTROL_ELEMENT); if( e0.length > 0 ){ var e1 = document.querySelectorAll(NEW_NOTI_NEWMARK_ELEMENT); if( e1.length > 0 ){ if( ++gi_chkNotificationCount < gi_chkNotificationCountMax ){ gtmr_waitClear = window.setTimeout( waitforNotificationClear, 1000 ); return; } } //新着数を示すタグが消えても背景色の色替えが戻らない事があるのでスクロールを操作する window.setTimeout( function(){ window.scrollTo(0, window.innerHeight);}, 5000 ); window.setTimeout( function(){ window.scrollTo(0, 0); gf_flgClearNotification = false; closePopupClearNewTweetMessage(); dispDebugTextWithTime("waitforNotificationClear : Scroll complete"); }, 5100 ); //console.log("★Finish!" + gi_chkNotificationCount); gi_chkNotificationCount = 0; e0[0].style.height = null; } } //DM新着があればポップアップを表示 function checkDMNotification(){ var msg = ""; var e0 = document.querySelectorAll(NEW_NOTI_DM_ELEMENT); if( e0.length > 0 ){ //表示中は閉じて開くのではなく何もせず戻る if( gelm_fixedPopupClearNewDM !== null ) return; var w1 = getDialogWidth(); msg += "
[" + toFormatedDateString(new Date()) + "]
新着のDMがあります
"; msg += "
"; msg += "
"; gelm_fixedPopupClearNewDM = dispPopupMessage(msg, -1, null, null, true, false); dispDebugTextWithTime("checkDMNotification : Display DM Page Notification"); var e = document.getElementById('ELM_DMNOTIFICATION_BTN1'); if( e !== null ){ e.onclick = function(){ dispDebugTextWithTime("checkDMNotification : Display DM Page Open"); window.open( TWITTER_URL2 + "/messages", '_blank' ); closePopupClearNewDM() }; } }else{ closePopupClearNewDM() } } /************************************************************ 情報表示部・ボタン生成関連関数 ************************************************************/ //情報表示部+ボタンのコントロールを消去する function removeInfoButtonElements(){ //IDで検索して消す for( var i=removeInfoButtonElements.length-1; i > -1; i-- ){ if( removeInfoButtonElements[i] != "" ){ var e = document.querySelectorAll('div["' + removeInfoButtonElements[i] + '"]'); for( var j=0; j BUTTON_LOCK_TIME ){ if( upd ){ gobj_buttonClickTime = dt; } return false; }else{ dispDebugTextWithTime("checkButtonLockTime(" + upd + ") : Locked[" + sub + "]", LOG_ERR); return true; } } //クリックで入力ダイアログを入力させるボタン部と自動更新のON/OFFをするボタン部を生成 function setupElement(parentElm){ //parentElm: 情報表示部を追加する親エレメント var idx = 0; var D_WIDTH = Number((DISPINFO_WIDTH).replace("px","")); var D_HEIGHT = Number((DISPINFO_HEIGHT).replace("px","")) //既にあったら消す removeInfoButtonElements(); //基準となる元エレメントのプロパティ parentElm.style.display = "flex"; parentElm.style.fontSize = gstrA_titleSize[gi_dispMode]; //親エレメント生成 gelm_allParent = document.createElement("div"); gelm_allParent.setAttribute("id",PARENT_BLOCK); gelm_allParent.style.display = "flex"; gelm_allParent.style.marginLeft = "3px"; gelm_allParent.style.marginRight = "3px"; gelm_allParent.style.backgroundColor = COLOR_BGCOLOR; gelm_allParent.style.borderWidth = "0px"; gelm_allParent.style.opacity = gf_dispUnitOpacity; gelm_allParent.style.zIndex = "7"; setStopEvents(gelm_allParent,true,true); parentElm.appendChild(gelm_allParent); if( gi_countPosition > BTN4_POSITION_NONE ){ //新着件数・受信件数表示ボタンのエレメント生成 gelm_btnCount = document.createElement("div"); gelm_btnCount.setAttribute("id",COUNTBTN_BLOCK); gelm_btnCount.style.display = "block"; gelm_btnCount.style.width = COUNTBTN_WIDTH; gelm_btnCount.style.height = DISPINFO_HEIGHT; gelm_btnCount.style.color = COLOR_RECVCOUNT; gelm_btnCount.style.backgroundColor = COLOR_COUNT_BG; gelm_btnCount.style.fontSize = gstrA_titleSize[gi_dispMode]; gelm_btnCount.style.border = COLOR_BORDER; gelm_btnCount.style.borderStyle = "solid"; gelm_btnCount.style.borderWidth = "1px"; gelm_btnCount.style.zIndex = "9"; gelm_btnCount.style.textAlign = "center"; gelm_btnCount.textContent = ""; gelm_btnCount.style.userSelect = "none"; setStopEvents(gelm_btnCount,true,true); //新着件数・受信件数表示ボタン上に置かれるボタンエレメント生成 gelm_btnCount2 = document.createElement("div"); gelm_btnCount2.setAttribute("id",COUNTBTN_BLOCK2); gelm_btnCount2.style.display = "block"; gelm_btnCount2.style.position = "absolute"; gelm_btnCount2.style.textAlign = "center"; gelm_btnCount2.style.width = COUNTBTN_WIDTH; gelm_btnCount2.style.height = DISPINFO_HEIGHT; gelm_btnCount2.style.marginLeft = "0px"; gelm_btnCount2.style.overflowX = "hidden"; gelm_btnCount2.style.overflowY = "hidden"; gelm_btnCount2.style.color = INFOBUTTON_FORE_COLOR; gelm_btnCount2.style.opacity = "0.0"; gelm_btnCount2.style.fontSize = gstrA_titleSize[gi_dispMode]; gelm_btnCount2.style.borderColor = INFOBUTTON_BORDER_COLOR; gelm_btnCount2.style.borderStyle = "solid"; gelm_btnCount2.style.borderWidth = "1px"; gelm_btnCount2.style.zIndex = "10"; if( giA_enableButton[3] ){//BTN4有効の場合 gelm_btnCount2.style.backgroundColor = INFOBUTTON_BG_COLOR; gelm_btnCount2.textContent = BTN_TXT_BTNC; gelm_btnCount2.onclick = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( clickInformationButton, 0, CON_BUTTON_CL); return false; }; gelm_btnCount2.oncontextmenu = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( clickInformationButton, 0, CON_BUTTON_CR); return false; }; }else{ gelm_btnCount2.style.backgroundColor = "transparent"; gelm_btnCount2.textContent = ""; } gelm_btnCount2.style.userSelect = "none"; setStopEvents(gelm_btnCount2,false,false); } //新着・受信件数を左端に表示 if( gi_countPosition == BTN4_POSITION_LEFT ){ gelm_allParent.appendChild(gelm_btnCount); gelm_allParent.appendChild(gelm_btnCount2); } //情報表示+BTN1〜3の親エレメント生成 gelm_allParent2 = document.createElement("div"); gelm_allParent2.setAttribute("id",PARENT_BLOCK2); gelm_allParent2.style.display = "flex"; gelm_allParent2.style.marginLeft = "0px"; gelm_allParent2.style.marginRight = "0px"; gelm_allParent2.style.backgroundColor = COLOR_BGCOLOR; gelm_allParent2.style.borderWidth = "0px"; gelm_allParent2.style.opacity = gf_dispUnitOpacity; gelm_allParent2.style.zIndex = "8"; setStopEvents(gelm_allParent2,true,true); gelm_allParent.appendChild(gelm_allParent2); //自動更新情報表示(情報表示部)のエレメント生成 gelm_dispInfo = document.createElement("div"); gelm_dispInfo.setAttribute("id",INFO_BLOCK); gelm_dispInfo.style.display = "block"; gelm_dispInfo.style.textAlign = "center"; gelm_dispInfo.style.width = DISPINFO_WIDTH; gelm_dispInfo.style.height = DISPINFO_HEIGHT; gelm_dispInfo.style.overflowX = "hidden"; gelm_dispInfo.style.overflowY = "hidden"; gelm_dispInfo.style.color = COLOR_GRAY; gelm_dispInfo.style.backgroundColor = COLOR_BGCOLOR; gelm_dispInfo.style.fontSize = gstrA_titleSize[gi_dispMode]; gelm_dispInfo.style.border = COLOR_BORDER; gelm_dispInfo.style.borderStyle = "solid"; gelm_dispInfo.style.borderWidth = "1px"; gelm_dispInfo.style.zIndex = "9"; gelm_dispInfo.textContent = ""; gelm_dispInfo.style.userSelect = "none"; setStopEvents(gelm_dispInfo,true,true); gelm_allParent2.appendChild(gelm_dispInfo); //情報表示部の上に置かれる左ボタンエレメント生成 gelm_btnLeft = document.createElement("div"); gelm_btnLeft.setAttribute("id",INFOLBTN_BLOCK); gelm_btnLeft.style.display = "block"; gelm_btnLeft.style.position = "absolute"; gelm_btnLeft.style.textAlign = "center"; gelm_btnLeft.style.width = (D_WIDTH / 3) + "px"; gelm_btnLeft.style.height = (D_HEIGHT - 2) + "px"; gelm_btnLeft.style.marginLeft = "0px"; gelm_btnLeft.style.overflowX = "hidden"; gelm_btnLeft.style.overflowY = "hidden"; gelm_btnLeft.style.color = INFOBUTTON_FORE_COLOR; gelm_btnLeft.style.opacity = "0.0"; gelm_btnLeft.style.fontSize = gstrA_titleSize[gi_dispMode]; gelm_btnLeft.style.borderColor = INFOBUTTON_BORDER_COLOR; gelm_btnLeft.style.borderStyle = "solid"; gelm_btnLeft.style.borderWidth = "1px"; gelm_btnLeft.style.zIndex = "10"; if( giA_enableButton[0] ){//BTN0有効の場合 gelm_btnLeft.style.backgroundColor = INFOBUTTON_BG_COLOR; gelm_btnLeft.textContent = BTN_TXT_BTNL; gelm_btnLeft.onclick = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( clickInformationButton, 0, CON_BUTTON_LL); return false; }; gelm_btnLeft.oncontextmenu = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( clickInformationButton, 0, CON_BUTTON_LR); return false; }; }else{ gelm_btnLeft.style.backgroundColor = "transparent"; gelm_btnLeft.textContent = ""; } gelm_btnLeft.style.userSelect = "none"; setStopEvents(gelm_btnLeft,false,false); gelm_allParent2.appendChild(gelm_btnLeft); //情報表示部の上に置かれる中ボタンエレメント生成 gelm_btnMid = document.createElement("div"); gelm_btnMid.setAttribute("id",INFOMBTN_BLOCK); gelm_btnMid.style.display = "block"; gelm_btnMid.style.position = "absolute"; gelm_btnMid.style.textAlign = "center"; gelm_btnMid.style.width = (D_WIDTH / 3) + "px"; gelm_btnMid.style.height = (D_HEIGHT - 2) + "px"; gelm_btnMid.style.marginLeft = (D_WIDTH / 3) + "px"; gelm_btnMid.style.overflowX = "hidden"; gelm_btnMid.style.overflowY = "hidden"; gelm_btnMid.style.color = INFOBUTTON_FORE_COLOR; gelm_btnMid.style.opacity = "0.0"; gelm_btnMid.style.fontSize = gstrA_titleSize[gi_dispMode]; gelm_btnMid.style.borderColor = INFOBUTTON_BORDER_COLOR; gelm_btnMid.style.borderStyle = "solid"; gelm_btnMid.style.borderWidth = "1px"; gelm_btnMid.style.zIndex = "10"; if( giA_enableButton[1] ){//BTN2有効の場合 gelm_btnMid.style.backgroundColor = INFOBUTTON_BG_COLOR; gelm_btnMid.textContent = BTN_TXT_BTNM; gelm_btnMid.onclick = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( clickInformationButton, 0, CON_BUTTON_ML); return false; }; gelm_btnMid.oncontextmenu = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( clickInformationButton, 0, CON_BUTTON_MR); return false; }; }else{ gelm_btnMid.style.backgroundColor = "transparent"; gelm_btnMid.textContent = ""; } gelm_btnMid.style.userSelect = "none"; setStopEvents(gelm_btnMid,false,false); gelm_allParent2.appendChild(gelm_btnMid); //情報表示部の上に置かれる右ボタンエレメント生成 gelm_btnRight = document.createElement("div"); gelm_btnRight.setAttribute("id",INFORBTN_BLOCK); gelm_btnRight.style.display = "block"; gelm_btnRight.style.position = "absolute"; gelm_btnRight.style.textAlign = "center"; gelm_btnRight.style.width = (D_WIDTH / 3) + "px"; gelm_btnRight.style.height = (D_HEIGHT - 2) + "px"; gelm_btnRight.style.marginLeft = (D_WIDTH * 2 / 3) + "px"; gelm_btnRight.style.overflowX = "hidden"; gelm_btnRight.style.overflowY = "hidden"; gelm_btnRight.style.color = INFOBUTTON_FORE_COLOR; gelm_btnRight.style.opacity = "0.0"; gelm_btnRight.style.fontSize = gstrA_titleSize[gi_dispMode]; gelm_btnRight.style.borderColor = INFOBUTTON_BORDER_COLOR; gelm_btnRight.style.borderStyle = "solid"; gelm_btnRight.style.borderWidth = "1px"; gelm_btnRight.style.zIndex = "10"; if( giA_enableButton[2] ){//BTN3有効の場合 gelm_btnRight.style.backgroundColor = INFOBUTTON_BG_COLOR; gelm_btnRight.textContent = BTN_TXT_BTNR; gelm_btnRight.onclick = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( clickInformationButton, 0, CON_BUTTON_RL); return false; }; gelm_btnRight.oncontextmenu = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( clickInformationButton, 0, CON_BUTTON_RR); return false; }; }else{ gelm_btnRight.style.backgroundColor = "transparent"; gelm_btnRight.textContent = ""; } gelm_btnRight.style.userSelect = "none"; setStopEvents(gelm_btnRight,false,false); gelm_allParent2.appendChild(gelm_btnRight); //ボタン親エレメント生成 gelm_btnParent = document.createElement("div"); gelm_btnParent.setAttribute("id",BUTTON_BLOCK); gelm_btnParent.style.display = "flex"; gelm_btnParent.style.height = DISPINFO_HEIGHT; gelm_btnParent.style.marginLeft = "0px"; gelm_btnParent.style.marginRight = "0px"; gelm_btnParent.style.borderWidth = "0px"; gelm_btnParent.style.zIndex = "8"; setStopEvents(gelm_btnParent,true,true); gelm_allParent2.appendChild(gelm_btnParent); //新着・受信件数を中央に表示 if( gi_countPosition == BTN4_POSITION_MID ){ gelm_btnParent.appendChild(gelm_btnCount); gelm_btnParent.appendChild(gelm_btnCount2); } //ヘルプダイアログボタンのエレメント生成 gelm_btnHelp = document.createElement("div"); gelm_btnHelp.setAttribute("id",HELP_BLOCK); gelm_btnHelp.style.display = "flex"; gelm_btnHelp.style.height = DISPINFO_HEIGHT; gelm_btnHelp.style.color = COLOR_GRAY; gelm_btnHelp.style.backgroundColor = COLOR_BGCOLOR; gelm_btnHelp.style.fontSize = gstrA_buttonSize[gi_dispMode]; gelm_btnHelp.style.border = COLOR_BORDER; gelm_btnHelp.style.borderStyle = "solid"; gelm_btnHelp.style.borderWidth = "1px"; gelm_btnHelp.style.textAlign = "center"; gelm_btnHelp.style.zIndex = "9"; gelm_btnHelp.textContent = BTN_TXT_HLP; gelm_btnHelp.style.userSelect = "none"; gelm_btnHelp.onclick = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( dispInfoDialog, 0); return false; }; gelm_btnHelp.oncontextmenu = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( dispReadDialog, 0); return false; }; setStopEvents(gelm_btnHelp,false,false); gelm_btnParent.appendChild(gelm_btnHelp); //インターバル設定ボタンのエレメント生成 gelm_btnInterval = document.createElement("div"); gelm_btnInterval.setAttribute("id",INTERVAL_BLOCK); gelm_btnInterval.style.display = "flex"; gelm_btnInterval.style.height = DISPINFO_HEIGHT; gelm_btnInterval.style.color = COLOR_GRAY; gelm_btnInterval.style.backgroundColor = COLOR_BGCOLOR; gelm_btnInterval.style.fontSize = gstrA_buttonSize[gi_dispMode]; gelm_btnInterval.style.border = COLOR_BORDER; gelm_btnInterval.style.borderStyle = "solid"; gelm_btnInterval.style.borderWidth = "1px"; gelm_btnInterval.style.zIndex = "9"; gelm_btnInterval.style.textAlign = "center"; gelm_btnInterval.textContent = BTN_TXT_INT; gelm_btnInterval.style.userSelect = "none"; gelm_btnInterval.onclick = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( dispSettingMessage, 0); return false; }; gelm_btnInterval.oncontextmenu = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( dispSystemSettingMessage, 0); return false; }; setStopEvents(gelm_btnInterval,false,false); gelm_btnParent.appendChild(gelm_btnInterval); //短周期タイマ設定ボタンのエレメント生成 gelm_btnShort = document.createElement("div"); gelm_btnShort.setAttribute("id",SHORT_BLOCK); gelm_btnShort.style.display = "flex"; gelm_btnShort.style.height = DISPINFO_HEIGHT; gelm_btnShort.style.color = COLOR_IDL_DISABL; gelm_btnShort.style.backgroundColor = COLOR_BGCOLOR; gelm_btnShort.style.fontSize = gstrA_buttonSize[gi_dispMode]; gelm_btnShort.style.border = COLOR_BORDER; gelm_btnShort.style.borderStyle = "solid"; gelm_btnShort.style.borderWidth = "1px"; gelm_btnShort.style.zIndex = "9"; gelm_btnShort.style.textAlign = "center"; gelm_btnShort.textContent = BTN_TXT_SRT; gelm_btnShort.style.userSelect = "none"; gelm_btnShort.onclick = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( onClickShortButton, 0 ); return false; }; gelm_btnShort.oncontextmenu = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( idleTimerChange, 0); return false; }; setStopEvents(gelm_btnShort,false,false); gelm_btnParent.appendChild(gelm_btnShort); //自動更新ON/OFF設定ボタンのエレメント生成 gelm_btnAutoOff = document.createElement("div"); gelm_btnAutoOff.setAttribute("id",AUTO_BLOCK); gelm_btnAutoOff.style.display = "flex"; gelm_btnAutoOff.style.height = DISPINFO_HEIGHT; gelm_btnAutoOff.style.color = COLOR_AUT_DISABL; gelm_btnAutoOff.style.backgroundColor = COLOR_BGCOLOR; gelm_btnAutoOff.style.fontSize = gstrA_buttonSize[gi_dispMode]; gelm_btnAutoOff.style.border = COLOR_BORDER; gelm_btnAutoOff.style.borderStyle = "solid"; gelm_btnAutoOff.style.borderWidth = "1px"; gelm_btnAutoOff.style.zIndex = "9"; gelm_btnAutoOff.style.textAlign = "center"; gelm_btnAutoOff.textContent = BTN_TXT_AUT; gelm_btnAutoOff.style.userSelect = "none"; gelm_btnAutoOff.onclick = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( switchAutoButton, 0); return false; }; gelm_btnAutoOff.oncontextmenu = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( resetRecvTime, 0); return false; }; setStopEvents(gelm_btnAutoOff,false,false); gelm_btnParent.appendChild(gelm_btnAutoOff); if( gi_dispMode == MODE_HOME ){ //ツイート欄ON/OFF設定ボタンのエレメント生成 gelm_btnEdit = document.createElement("div"); gelm_btnEdit.setAttribute("id",EDITBTN_BLOCK); gelm_btnEdit.style.display = "flex"; gelm_btnEdit.style.height = DISPINFO_HEIGHT; gelm_btnEdit.style.color = COLOR_RECVCOUNT; gelm_btnEdit.style.backgroundColor = COLOR_BGCOLOR; gelm_btnEdit.style.fontSize = gstrA_buttonSize[gi_dispMode]; gelm_btnEdit.style.border = COLOR_BORDER; gelm_btnEdit.style.borderStyle = "solid"; gelm_btnEdit.style.borderWidth = "1px"; gelm_btnEdit.style.zIndex = "9"; gelm_btnEdit.style.textAlign = "center"; gelm_btnEdit.textContent = " "; gelm_btnEdit.style.userSelect = "none"; gelm_btnEdit.onclick = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( onClickEditSwitchButton, 0); return false; }; gelm_btnEdit.oncontextmenu = function(e){ e.stopPropagation(); if(checkButtonLockTime(true)) return false; window.setTimeout( onRClickEditSwitchButton, 0); return false; }; setStopEvents(gelm_btnEdit,false,false); gelm_btnParent.appendChild(gelm_btnEdit); swichEditColumn(); } //新着・受信件数のボタンを右端に表示 if( gi_countPosition == BTN4_POSITION_RIGHT ){ //件数表示部+上ボタン(BTN4)の親エレメント生成 gelm_allParent3 = document.createElement("div"); gelm_allParent3.setAttribute("id",PARENT_BLOCK3); gelm_allParent3.style.display = "flex"; gelm_allParent3.style.marginLeft = "0px"; gelm_allParent3.style.marginRight = "0px"; gelm_allParent3.style.backgroundColor = COLOR_BGCOLOR; gelm_allParent3.style.borderWidth = "0px"; gelm_allParent3.style.opacity = gf_dispUnitOpacity; gelm_allParent3.style.zIndex = "8"; setStopEvents(gelm_allParent3,true,true); gelm_btnParent.appendChild(gelm_allParent3); gelm_allParent3.appendChild(gelm_btnCount); gelm_allParent3.appendChild(gelm_btnCount2); } //ボタン機能のヘルプポップアップを表示 addEventToolTips( gelm_btnLeft, ++idx, BTN_TXT_BTNL, CON_BUTTON_LL, CON_BUTTON_LR, giA_enableButton[0] ); addEventToolTips( gelm_btnMid, ++idx, BTN_TXT_BTNM, CON_BUTTON_ML, CON_BUTTON_MR, giA_enableButton[1] ); addEventToolTips( gelm_btnRight, ++idx, BTN_TXT_BTNR, CON_BUTTON_RL, CON_BUTTON_RR, giA_enableButton[2] ); addEventToolTips( gelm_btnShort, ++idx, BTN_TXT_SRT, BTNID_SHORT, BTNID_SHORT+1 ); addEventToolTips( gelm_btnInterval, ++idx, BTN_TXT_INT, BTNID_INTVL, BTNID_INTVL+1 ); addEventToolTips( gelm_btnAutoOff, ++idx, BTN_TXT_AUT, BTNID_ATOFF, BTNID_ATOFF+1 ); addEventToolTips( gelm_btnHelp, ++idx, BTN_TXT_HLP, BTNID_HELP, BTNID_HELP+1 ); if( gi_dispMode == MODE_HOME ){ addEventToolTips( gelm_btnEdit, ++idx, BTN_TXT_ED1 + " / " + BTN_TXT_ED0, BTNID_EDIT, BTNID_EDIT+1 ); } if( gi_countPosition > BTN4_POSITION_NONE ){ addEventToolTips( gelm_btnCount2, ++idx, BTN_TXT_BTNC, CON_BUTTON_CL, CON_BUTTON_CR, giA_enableButton[3] ); } } //ボタン類のツールチップ共通処理 function addEventToolTips(obj,idx,label,btn1,btn2,en=true){ //obj: 対象オブジェクト //idx: 対象オブジェクトの固有インデックス //label: 表示ラベル //btn1: 情報表示部ボタンの左クリック用インデックス //btn2: 情報表示部ボタンの右クリック用インデックス //en: ボタンの有効無効状態 gelmA_fixedToolTips[idx] = null; obj.addEventListener('mouseover', function(){ var i, msg = getButtonToolTipsHTML(label,btn1,btn2); //編集中とボタン排他期間は操作させない if( gi_dispMode == MODE_HOME && isHomeEditControlActive() || checkButtonLockTime() ){ return; } gi_onButtonHover = 1; if( gi_dispToolTipsPopup && en ){ if( gelmA_fixedToolTips[idx] === null ){ gelmA_fixedToolTips[idx] = dispPopupMessage(msg, gi_displayHelpToolTipsPopupCloseTimeSec, COLOR_TOOLTIPS_FGCOLOR, COLOR_TOOLTIPS_BGCOLOR, true, false, true); }else{ if( gelmA_fixedToolTips[idx].style.display == "none" ){ gelmA_fixedToolTips[idx].style.display = null; } } for( i=1; i 0; i-- ){ if( gelmA_fixedToolTips[i] !== null ){ //dispDebugTextWithTime("closePopupToolTips : clearAll idx=[" + i + "]"); closePopupMessage(gelmA_fixedToolTips[i]); gelmA_fixedToolTips[i] = null; } } }else{ //固有インデックスを探して該当のオブジェクトを消去 if( gelmA_fixedToolTips[idx] !== null ){ //dispDebugTextWithTime("closePopupToolTips : clearOne idx=[" + idx + "]"); closePopupMessage(gelmA_fixedToolTips[idx]); gelmA_fixedToolTips[idx] = null; } } //生きているオブジェクトがあるか for( i=1; i max ) ? max : ((window.innerWidth < min ) ? min : Math.floor(window.innerWidth * 0.9)); var msg = ""; msg += "
[ " + label + " ] ボタン機能割付
" msg += ""; msg += ""; msg += ""; msg += "
左クリック :" + getButtonFunction(btn1) + "右クリック :" + getButtonFunction(btn2) + "
"; return msg; } //ボタンに割り付けた機能一覧の取得 function getButtonFunction(btnIdx){ //btnIdx: 情報表示部ボタンのインデックス //return: 機能一覧文字列 //通知ページかどうか var ntf = (gi_dispMode == MODE_NOTI) ? true : false; //スクロール中かどうか var scr = (window.pageYOffset <= SCROLL_LIMIT ) ? false : true; //先頭にスクロールが有効になっているかどうか var sct = false; var msg = ""; if( btnIdx < MAX_CON_BUTTON ){ if( gi_findMode ){ msg += "
 既読マーク捜索中断"; } if( giA_scrToTopButton[btnIdx] ){ if( scr ){ sct = true; msg += "
 先頭にスクロール"; }else{ msg += "
 先頭にスクロール"; } } if( giA_oneShotShortTimer[btnIdx] ){ msg += "
 短周期処理の単発実行"; } if( gi_enableReadPointCheckBox && giA_manualUpdateAutoCheck[btnIdx] && !ntf ){ if( scr ){ msg += "
 自動既読マーク"; }else{ msg += "
 自動既読マーク"; } } if( giA_manualUpdateTrigger[btnIdx] && !ntf ){ if( scr ){ msg += "
 手動更新"; }else{ msg += "
 手動更新"; } } if( giA_updateContinuousButton[btnIdx] && !ntf ){ if( scr ){ msg += "
 新着積み上げ"; }else{ msg += "
 新着積み上げ"; } } if( gi_enableReadPointCheckBox && giA_findReadPointButton[btnIdx] && !ntf ){ msg += "
 既読マーク捜索"; } if( gi_enableReadPointCheckBox && giA_scrTopMarkButton[btnIdx] && !ntf){ //新着積み上げか捜索モードとペアで使う場合はスクロール位置に関係無く有効 if( (scr || giA_updateContinuousButton[btnIdx] || giA_findReadPointButton[btnIdx]) && ! sct ){ msg += "
 先頭で既読マーク"; }else{ msg += "
 先頭で既読マーク"; } } if(ntf && (btnIdx % 2)){ msg += "
 タイマ時間リセット"; } if(giA_clearNewNotification[btnIdx] && ntf){ msg += "
 新着表示色クリア"; } if( gi_findMode ){ msg += "
"; } return msg; } switch(btnIdx){ case BTNID_SHORT://左クリック if(DEBUG_MODE){ msg += "
 OPEN DEBUG WINDOW"; }else{ msg += "
 短周期処理の単発実行"; } break; case BTNID_SHORT + 1://右クリック msg += "
 短周期タイマ切替"; break; case BTNID_INTVL://左クリック msg += "
 コンフィグ設定"; break; case BTNID_INTVL + 1://右クリック msg += "
 システムコンフィグ設定"; break; case BTNID_ATOFF://左クリック msg += "
 自動更新OFF切替"; break; case BTNID_ATOFF + 1://右クリック msg += "
 タイマ時間リセット"; break; case BTNID_HELP://左クリック msg += "
 ヘルプダイアログ表示"; break; case BTNID_HELP + 1://右クリック if(gi_enableReadPointCheckBox && !ntf){ msg += "
 既読情報ダイアログ表示"; }else{ msg += "
 (none)"; } break; case BTNID_EDIT://左クリック msg += "
 ツイート入力欄表示切替"; break; case BTNID_EDIT + 1://右クリック msg += "
 先頭カラムの新着表示切替"; break; } if( msg == "" ){ msg = "
 (none)"; } return msg; } //上部割り付けボタンのクリック操作によるスクロール・短周期処理の単発実行・更新トリガ・自読既読マーク・既読マーク捜索 function clickInformationButton(btnId){ //btnId: 情報表示部ボタンのインデックス var dt = new Date(); closePopupToolTips(); //編集中は操作させない if( gi_dispMode == MODE_HOME && isHomeEditControlActive() ){ dispDebugTextWithTime("clickInformationButton[" + btnId + "] : Edit active", LOG_OPE); return; } //既読捜索モード中はどのボタンを押しても中断 if( gi_findMode ){ resetFindModeParams(); if(gi_findModeDispPopup){ dispPopupMessage("既読ポイント捜索を中止しました" , gi_displayPopupCloseTimeSec, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_FIND); closePopupFindAll(); } return; } //新着積み上げ動作中は何もしない if( gf_continuousDOMWaiting || (gi_continuousPhase != CONT_IDLE && gi_continuousPhase != CONT_FINISH) ) return; //スクロールがほぼは最上部なら先頭に戻す(既読マークとスクロールマークが設定されていてトップスクロールとトリガなしなら動かさない) if( window.pageYOffset <= SCROLL_LIMIT && ( !(giA_manualUpdateAutoCheck[btnId] && giA_scrTopMarkButton[btnId] && !giA_scrToTopButton[btnId] && !giA_manualUpdateTrigger[btnId] ) ) ){ window.scrollTo(0, 0); dispDebugTextWithTime("clickInformationButton[" + btnId + "] : Scroll to (0,0)", LOG_OPE); } //通知ページは右クリックされたらタイマリセットを行う(◆ボタンが無いので強制リロードをキャンセルできないため) if( gi_dispMode == MODE_NOTI && (! gf_flgClearNotification) && (btnId == CON_BUTTON_LR || btnId == CON_BUTTON_MR || btnId == CON_BUTTON_RR || btnId == CON_BUTTON_CR) ){ gdt_lastRecvTime = gdt_lastTriggerTime = dt; gi_updateCountMs = giA_updateIntervalMs[gi_dispMode] - 1000; dispDebugTextWithTime("clickInformationButton[" + btnId + "] : Timer reset", LOG_OPE); } //次回スクロール位置を先頭に戻したら既読マークする(新着積み上げと併用する場合は終わった後にモードを切り替えるので、ここではしない) if( giA_scrTopMarkButton[btnId] && ! giA_manualUpdateTrigger[btnId] && gi_enableReadPointCheckBox && gi_dispMode != MODE_NOTI ){ if( giA_findReadPointButton[btnId] ){ //捜索モードと併用 startModeScrTopMark(true); }else{ //単独使用 startModeScrTopMark(false); } dispDebugTextWithTime("clickInformationButton[" + btnId + "] : Scroll top mark mode", LOG_OPE); } //既読ポイントを捜索するモードに移行する(手動更新や既読マーク更新は設定されていても動作しない if( giA_findReadPointButton[btnId] && gi_enableReadPointCheckBox && gi_dispMode != MODE_NOTI ){ startReadPointFindingMode(); dispDebugTextWithTime("clickInformationButton[" + btnId + "] : Start find mark mode", LOG_OPE); return; } //スクロール中は最上部のアーティクルが読まれていない状態の事があるので先頭よりちょっと下に戻るのみ(先頭に戻すとトリガされてしまう) if( giA_scrToTopButton[btnId] ){ if( window.pageYOffset > SCROLL_LIMIT && ! gf_scrollOperation ){ if( gi_scrToTopModeDispPopup ){ closePopupScrToTop(); gelm_fixedScrToTop = dispPopupMessage("先頭にスクロールを戻します", -1, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_TTOP); } //スクロール操作の排他開始 gf_scrollOperation = true; if( gi_dispMode != MODE_LIST || window.pageYOffset <= LIST_PAGE_SCROLL_LIMIT ){ dispDebugTextWithTime("clickInformationButton : Normal-scroll start : " + Math.floor(window.pageYOffset), LOG_OPE); window.setTimeout( function(){ window.scrollTo(0, SCROLL_LIMIT ); }, 100 ); window.setTimeout( function(){ checkScrollComplete(); }, gi_splitScrollIntervalMs ); }else{ //CSS切り替えポイントを一気に跨がないように分割してスクロールする dispDebugTextWithTime("clickInformationButton : Split-scroll start : " + Math.floor(window.pageYOffset), LOG_OPE); window.setTimeout( function(){ window.scrollTo(0, LIST_PAGE_SCROLL_LIMIT ); }, 100 ); window.setTimeout( function(){ checkScrollLimitOnSplitScroll(); }, gi_splitScrollIntervalMs ); } return; } } //短周期処理のワンショット実施 if( gi_idleShortTimer && giA_oneShotShortTimer[btnId] ){ replaceElementsOneShot(); dispDebugTextWithTime("clickInformationButton[" + btnId + "] : replaceElementsOneShot()", LOG_OPE); //for DEBUG ※ローカルストレージの保存データオブジェクトをコンソールに表示 if( btnId == CON_BUTTON_RL ){ loadStorageData(); console.log("ONESHOT PseudoTwDk: Setting="); console.dir(gobj_localData); } } //DMがあれば通知ページにポップアップ表示 if( gi_dispMode == MODE_NOTI ){ checkDMNotification(); } //通知ページの新着表示を戻す if( giA_clearNewNotification[btnId] && gi_dispMode == MODE_NOTI ){ clearNewNotification(); return; } if( gi_dispMode != MODE_HOME && gi_dispMode != MODE_LIST && gi_dispMode != MODE_USER && gi_dispMode != MODE_SEAR ) return; if( window.pageYOffset <= SCROLL_LIMIT ){ //自動で最新表示中のアーティクルを既読マークする if( giA_manualUpdateAutoCheck[btnId] && gi_enableReadPointCheckBox ){ if( gi_updateContinuousDispPopup && giA_manualUpdateTrigger[btnId] && giA_updateContinuousButton[btnId] ){ dispPopupMessage("先頭記事を既読マークします", gi_displayPopupCloseTimeSec, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_MARK); } //連続更新前にストレージから読み出す loadStorageData(); //マークを先頭記事から更新 updateReadCheck(); //連続更新後にストレージに格納する saveStorageData(); } } //更新禁止期間によって抑止されている時はトリガさせない if( gi_colorType == TYPE_HOLDTM ) return; //積み上げ更新の終了処理中はスクロール系やマーク系は許可するがトリガはさせない if( gi_continuousPhase != CONT_IDLE ) return; //前回の手動更新から時間が経過していたらトリガ if( giA_manualUpdateTrigger[btnId] ){ if( dt.getTime() - gdt_lastTriggerTime.getTime() > gi_manualUpdateIntervalSec * 1000 ){ //色替え・手動更新表示 forceUpdateColor(COLOR_UPDATE, TXT_MANUALUPDATE); //更新トリガの時間を記録 gdt_lastTriggerTime = dt; //先頭に戻してからトリガ window.scrollTo(0, 0); //手動でトリガ execTrigger(false, btnId); dispDebugTextWithTime("clickInformationButton[" + btnId + "] : Manual execTrigger()", LOG_OPE); //手動でトリガを掛けたのでインターバル時間はリセット gi_updateCountMs = 0; //先頭でマークと併用する場合 if( giA_scrTopMarkButton[btnId] ){ gi_contAfterTopMark = 1; } } } } //分割スクロールの中間ポイント完了待ち function checkScrollLimitOnSplitScroll(){ var elm = document.querySelectorAll('body:not([' + gstr_scrScrollList +'])'); if( elm.length > 0 ){ dispDebugTextWithTime("checkScrollLimitOnSplitScroll : Split-scroll continue : " + Math.floor(window.pageYOffset)); window.setTimeout( function(){ window.scrollTo(0, SCROLL_LIMIT ); }, gi_splitScrollIntervalMs ); window.setTimeout( function(){ checkScrollComplete(); }, gi_splitScrollIntervalMs * 2 ); }else{ dispDebugTextWithTime("checkScrollLimitOnSplitScroll : Split-scroll waiting : " + Math.floor(window.pageYOffset)); window.setTimeout( function(){ window.scrollTo(0, LIST_PAGE_SCROLL_LIMIT ); }, gi_splitScrollIntervalMs ); window.setTimeout( function(){ checkScrollLimitOnSplitScroll(); }, gi_splitScrollIntervalMs * 2 ); } //短周期タイマが止まっていたら再開されるようワンショット実行 replaceElementsOneShot(); } //スクロールの完了待ち function checkScrollComplete(){ if( Math.floor(window.pageYOffset) <= SCROLL_LIMIT ){ dispDebugTextWithTime("checkScrollComplete : Scroll complete : " + Math.floor(window.pageYOffset)); if( gi_scrToTopModeDispPopup ){ closePopupScrToTop(); dispPopupMessage("先頭にスクロールしました", gi_displayPopupCloseTimeSec, COLOR_POPUP_FGCOLOR, COLOR_POPUP_BGCOLOR_TTOP); } gf_scrollOperation = false; }else{ dispDebugTextWithTime("checkScrollComplete : Scroll waiting : " + Math.floor(window.pageYOffset)); window.setTimeout( function(){ window.scrollTo(0, SCROLL_LIMIT ); }, gi_splitScrollIntervalMs ); window.setTimeout( function(){ checkScrollComplete(); }, gi_splitScrollIntervalMs * 2 ); } //短周期タイマが止まっていたら再開されるようワンショット replaceElementsOneShot(); } /************************************************************ ボタン押下・設定切り替え関連関数 ************************************************************/ //短周期処理ボタン押下処理 function onClickShortButton(){ if( ! DEBUG_MODE ){ replaceElementsOneShot(); }else{ debugFunction(); } } //自動更新をON/OFFする(OFFでは強制停止、ONの時はスクロールバーの位置やエディット入力にフォーカスがあるか無いかで判定する従来の動作をする) function switchAutoButton(){ closePopupToolTips(); var u = getPageURL(); if( u == "" ) return; if( gelm_btnAutoOff === null ) return; if( gi_modeAutoOff == 1 ){ //AUTO = ONにする gi_modeAutoOff = 0; if(u.length > 2){ saveSetting( AUTOOFF_HEADER, u, 0 ); dispPopupMessage("自動更新を通常モードに切り替えました", gi_displayPopupCloseTimeSec); } }else{ //AUTO = OFFにする gi_modeAutoOff = 1; if(u.length > 2){ saveSetting( AUTOOFF_HEADER, u, 1 ); dispPopupMessage("自動更新を強制OFFモードに切り替えました", gi_displayPopupCloseTimeSec); } } gdt_lastTriggerTime = gdt_lastRecvTime = new Date(); gi_updateCountMs = giA_updateIntervalMs[gi_dispMode] - 1000; } //レコード更新時間をリセットし、自動更新・強制リロードまでの時間を再カウントする function resetRecvTime(){ closePopupToolTips(); gdt_lastRecvTime = new Date(); gi_updateCountMs = 0; dispPopupMessage("自動更新タイマと強制リロードまでの時間をリセットしました", gi_displayPopupCloseTimeSec); } //短周期タイマの常時動作切り替え function idleTimerChange(){ closePopupToolTips(); var u = getPageURL(); if( u == "" ) return; if( gi_idleShortTimer == 0 ){ gi_idleShortTimer = 1; dispPopupMessage("短周期タイマを都度停止するモードに切り替えました", gi_displayPopupCloseTimeSec); }else{ gi_idleShortTimer = 0; dispPopupMessage("短周期タイマを常時稼動モードに切り替えました", gi_displayPopupCloseTimeSec); } if(u.length > 2){ saveSetting( IDLETM_HEADER, u, gi_idleShortTimer ); } //どちらの設定であっても切り替えられたら短周期ワンショット replaceElementsOneShot(); } function isHomeEditControlActive(){ //return: 入力中・エディットにフォーカスあり=true //エディット入力中 var searchCandidate = document.body.querySelectorAll(EDIT_CONTROL_BLOCK); var focusElement = document.activeElement; if(searchCandidate.length > 0) { if(searchCandidate[0].innerHTML != ""){ dispDebugTextWithTime("isHomeEditControlActive : innerHTML is not empty", LOG_WARN); //編集していた時間を記録 gobj_editTime = new Date(); //エディット欄が閉じてしまっていたら開く if( gi_hideEditControl ){ gi_hideEditControl = 0; swichEditColumn(); } return true; } } //ツイート入力などにフォーカスが当たっている場合には処理しないようにする(フォーカスが外れる) var focusAttr = focusElement.getAttribute("data-testid"); if(focusAttr !== null){ if(focusAttr != "tweet" && focusAttr != "retweet" && focusAttr != "unretweet" && focusAttr != "like" && focusAttr != "unlike" && focusAttr != "AppTabBar_Home_Link"){ dispDebugTextWithTime("isHomeEditControlActive : focusAttr=" + focusAttr, LOG_WARN); return true; } } return false; } //複数件ツイート完了後にエディット欄に残った本文をクリアする function clearEditControl(){ //エディット入力中 var e0 = document.body.querySelectorAll(EDIT_CONTROL_BLOCK); if(e0.length > 0) { if(e0[0].innerHTML != ""){ e0[0].innerHTML = ""; } } } //ツイート欄の表示非表示切り替えのボタンイベント function onClickEditSwitchButton(){ closePopupToolTips(); if( isHomeEditControlActive() && ! gi_hideEditControl ) return; gi_hideEditControl = (gi_hideEditControl==0)?1:0; swichEditColumn(); dispDebugTextWithTime("onClickEditSwitchButton : swichEditColumn", LOG_OPE); } //Home上部の新着ツイート件数の表示非表示切り替えのボタンイベント function onRClickEditSwitchButton(){ closePopupToolTips(); gi_hideNumberNewTweet=(gi_hideNumberNewTweet==0)?1:0; swichDispNumberNewTweet(0); } //ツイート欄の表示非表示切り替え function swichEditColumn(){ if( gi_dispMode != MODE_HOME ) return; var e0, v; e0 = document.querySelectorAll('div[aria-label="ホームタイムライン"] > div:nth-of-type(3)'); if( e0.length > 0 ){ if( ! gi_hideEditControl ){ //表示へ切り替え e0[0].setAttribute(EDITSW_BLOCK, "0"); e0[0].style.display = null; gelm_btnEdit.textContent = " " + BTN_TXT_ED1 + " "; }else{ //非表示へ切り替え e0[0].setAttribute(EDITSW_BLOCK, "1"); e0[0].style.display = "none"; gelm_btnEdit.textContent = " " + BTN_TXT_ED0 + " "; } v = loadSetting( EDITHIDE_HEADER, KEY_SYSTEM ); if( (v === null && gi_hideEditControl != gi_defaultHideEditControl) || (v != null && v != gi_hideEditControl) ){ saveSetting( EDITHIDE_HEADER, KEY_SYSTEM, gi_hideEditControl ); } //console.log("★saveSetting" + EDITHIDE_HEADER + " = " + gi_hideEditControl); } } //先頭カラム新着件数表示の表示非表示切り替え function swichDispNumberNewTweet(noMessage){ //noMessage: true=ポップアップメッセージ表示なし / false:ポップアップメッセージ表示あり if( gi_dispMode != MODE_HOME ) return; var e0, e1, v; //要素変更 e0 = document.querySelectorAll('body'); if( e0.length > 0 ){ if( gi_hideNumberNewTweet ){ e0[0].setAttribute(gstr_scrNewTweetAttr, 'false'); e0[0].display = "none"; }else{ e0[0].setAttribute(gstr_scrNewTweetAttr, 'true'); e0[0].display = null; } v = loadSetting( NEWTWDISP_HEADER, KEY_SYSTEM ); if( (v === null && gi_hideNumberNewTweet != gi_defaultHideNumberNewTweet) || (v != null && v != gi_hideNumberNewTweet) ){ saveSetting( NEWTWDISP_HEADER, KEY_SYSTEM, gi_hideNumberNewTweet ); } if( ! noMessage ){ if( gi_hideNumberNewTweet ){ dispPopupMessage("先頭カラムの新着件数表示をOFFにしました", gi_displayPopupCloseTimeSec); }else{ dispPopupMessage("先頭カラムの新着件数表示をONにしました", gi_displayPopupCloseTimeSec); } } if(gi_idleShortTimer&& gtmr_shortTimer === null && gi_initComplete == 1 ){ replaceElementsOneShot(); } } } /************************************************************ ポップアップ表示関連関数 ************************************************************/ //ポップアップタイプのボタン付きダイアログを表示 function popupConfirm(dispMsg, btn1Text, btn1Func, btn2Text, btn2Func, btn3Text, btn3Func){ //dispMsg: 表示する文字列 //btn1Text: ボタン1に表示する文字列 //btn1Func: ボタン1押下時に呼ぶ関数 //btn2Text: ボタン2に表示する文字列 //btn2Func: ボタン2押下時に呼ぶ関数 //btn3Text: ボタン3に表示する文字列 //btn3Func: ボタン3押下時に呼ぶ関数 //ret: ポップアップオブジェクト var msg = "", e, ret, w1 = getDialogWidth(); msg += "
" + dispMsg + ""; if( btn1Text != "" && btn1Text !== null && btn1Text !== undefined ){ msg += "
"; } if( btn2Text != "" && btn2Text !== null && btn2Text !== undefined ){ msg += "
"; } if( btn3Text != "" && btn3Text !== null && btn3Text !== undefined ){ msg += "
"; } msg += "
"; ret = dispPopupMessage(msg, -1, null, null, true, false); if( btn1Text != "" && btn1Text !== null && btn1Text !== undefined ){ e = document.getElementById('ELM_CONFIRM_BTN1'); if( e !== null ){ e.onclick = btn1Func; e.style.marginTop = e.style.marginBottom = "3px"; } } if( btn2Text != "" && btn2Text !== null && btn2Text !== undefined ){ e = document.getElementById('ELM_CONFIRM_BTN2'); if( e !== null ){ e.onclick = btn2Func; e.style.marginTop = e.style.marginBottom = "3px"; } } if( btn3Text != "" && btn3Text !== null && btn3Text !== undefined ){ e = document.getElementById('ELM_CONFIRM_BTN3'); if( e !== null ){ e.onclick = btn3Func; e.style.marginTop = e.style.marginBottom = "3px"; } } return ret; } //ポップアップのためのエレメントを生成してメッセージを下部に表示する function dispPopupMessage(msg, tim_sec, fgcolor=null, bgcolor=null, typeHTML=false, closeOnClick=true, floatOnTop=false, debugWindow=false){ //msg: 表示テキスト, //tim_sec: 表示時間(-1指定時は自動的に消さない), //fgcolor: 文字色rgbテキスト(省略時白) //bgcolor: 背景色rgbテキスト(省略時Twitterテーマカラー) //typeHTML: true=テキストでは無くinnerHTMLを差し込む //closeOnClick: true=ポップアップ自体のクリックで閉じる動作をする / false=しない //floatOnTop: true=上に固定ポップアップする / false=しない //debugWindow: true=デバッグ用表示 //return: ポップアップオブジェクト if( gi_displayPopupCloseTimeSec <= 0 ) return; if( ! floatOnTop && ! typeHTML ){ dispDebugTextWithTime(msg, LOG_DIAG); } var e0, e1, e2, e3, e4, e5, e6, e7; var fg = COLOR_FGCOLOR; var bg = COLOR_BGCOLOR; var isNotHTML, nowObj, nowTime, endTime = ""; var max = (DIALOG_MAX_WIDTH).replace("px",""); var min = (DIALOG_MIN_WIDTH).replace("px",""); var w1 = (window.innerWidth > max ) ? max : ((window.innerWidth < min ) ? min : window.innerWidth); nowObj = new Date(); nowTime = nowObj.getTime(); isNotHTML = ! typeHTML; if( tim_sec != -1 ){ //複数のポップアップが積み重なるのを許可するため、消去予定時間をエレメントに付加しておく endTime = nowTime + (tim_sec * 1000); } if( fgcolor !== null ){ fg = fgcolor; } if( bgcolor === null ){ //Twitterの色設定に依存するツイートボタン色から背景色を拾ってくる e7 = document.querySelectorAll('a[data-testid="SideNav_NewTweet_Button"]'); if( e7.length > 0 ){ bg = window.getComputedStyle(e7[0], null).getPropertyValue('background-color'); } }else{ bg = bgcolor; } //要らないクラスIDとかありそうだけど、実際ツイート後に出るポップアップの要素をそのままコピー e0 = document.querySelectorAll('div[id="react-root"] div[id="layers"] > div:nth-of-type(1) > div:nth-of-type(1)'); if( e0.length > 0 ){ e1 = document.createElement("div"); e1.setAttribute("id",POPUP_BLOCK); //e1.setAttribute("class","css-175oi2r r-12vffkv"); e1.style.backgroundColor = COLOR_CLEAR; e1.style.width = "100%"; setStopEvents(e1); if( endTime != "" ){ e1.setAttribute(POPUP_ENDTIME, endTime); } e1.style.zIndex = "99"; if( floatOnTop ){ e1.style.position = "fixed"; e1.style.height = gi_floatPopupHeight + "px"; e1.style.bottom = (window.innerHeight - gi_floatPopupHeight - gi_floatPopupMargin) + "px"; } e2 = document.createElement("div"); e2.setAttribute("id",POPUP_BLOCK + "-1"); e2.setAttribute("class", "css-175oi2r r-1jgb5lz r-633pao r-13qz1uu"); if( ! floatOnTop ){ e2.style.backgroundColor = bg; }else{ //ツールチップにする場合は内部のテーブルより外側は透明にする e2.style.backgroundColor = COLOR_CLEAR; } e2.style.zIndex = "99"; if( ! floatOnTop && ! debugWindow ){ e2.style.width = w1 + "px"; }else{ e2.style.width = "100%"; } e1.appendChild(e2); e3 = document.createElement("div"); e3.setAttribute("id",POPUP_BLOCK + "-2"); e3.setAttribute("class", "css-175oi2r r-1awozwy r-18u37iz r-1wtj0ep r-q81ovl r-105ug2t r-o7fkjf r-1i6wzkk"); e3.setAttribute("role", "alert"); e3.setAttribute("data-testid", "toast"); e3.setAttribute("style", "transition-duration: 0ms; transition-timing-function: cubic-bezier(0, 0, 1, 1);"); if( ! floatOnTop ){ e3.style.backgroundColor = bg; }else{ e3.style.backgroundColor = COLOR_CLEAR; e3.style.justifyContent = "center"; } if( debugWindow ){ e3.style.justifyContent = "center"; e3.style.paddingLeft = "2px"; e3.style.paddingRight = "2px"; e3.style.paddingTop = "2px"; e3.style.paddingBottom = "2px"; } e3.style.zIndex = "99"; e3.style.width = "100%"; e2.appendChild(e3); e4 = document.createElement("div"); e4.setAttribute("id",POPUP_BLOCK + "-3"); e4.setAttribute("class", "css-901oao r-jwli3a r-1wbh5a2 r-1tl8opc r-1b43r93 r-16dba41 r-hjklzo r-bcqeeo r-1qfz7tf r-qvutc0"); e4.setAttribute("dir", "ltr"); if( closeOnClick ){ e4.onclick = function(e){e.stopPropagation(); closePopupMessage(e.target); return false;}; } if( ! floatOnTop ){ e4.style.backgroundColor = bg; }else{ e4.style.backgroundColor = COLOR_CLEAR; } if( debugWindow ){ e4.style.paddingLeft = "2px"; e4.style.paddingRight = "2px"; e4.style.paddingTop = "2px"; e4.style.paddingBottom = "2px"; } e4.style.zIndex = "99"; e3.appendChild(e4); e5 = document.createElement("span"); e5.setAttribute("id",POPUP_BLOCK + "-4"); e5.setAttribute("class", "css-901oao css-16my406 r-1tl8opc r-bcqeeo r-qvutc0"); if( ! floatOnTop ){ e5.style.backgroundColor = bg; }else{ e5.style.backgroundColor = COLOR_CLEAR; } e5.style.zIndex = "99"; e4.appendChild(e5); e6 = document.createElement("span"); e6.setAttribute("type","button"); e6.setAttribute("id",POPUP_BLOCK + "-5"); e6.style.zIndex = "99"; e6.style.pointerEvents = "auto"; e6.style.backgroundColor = bg; e6.style.color = fg; if( isNotHTML ){ e6.insertAdjacentHTML("beforeend", "[" + toFormatedDateString(nowObj) + "]
" + msg); }else{ e6.insertAdjacentHTML("beforeend", msg); } if( closeOnClick ){ e6.onclick = function(e){e.stopPropagation(); closePopupMessage(e.target); return false;}; } e5.appendChild(e6); if( ! debugWindow ){ e0[0].insertBefore(e1, e0[0].firstElementChild); }else{ e0[0].appendChild(e1); } if( floatOnTop ){ e7 = document.getElementById('PTD_POPUP_TOOLTIPS'); if( e7 !== null ){ e7.style.backgroundColor = bg; } } if( tim_sec != -1 ){ window.setTimeout( closePopupMessage, tim_sec * 1000 ); } return e1; } } //ポップアップを消去 function closePopupMessage(obj=null){ //obj: 閉じるポップアップのオブジェクト / null時は経過時間を判定して表示中のポップアップを閉じる var dt = (new Date()).getTime(); var val, attrTime, retry = 0, flg = false; if( obj != null ){ //console.log("★popupRemoved onClick0 : [" + obj + "]"); while(obj.getAttribute("id") != POPUP_BLOCK){ //console.log("★popupRemoved onClick1 : [" + obj + "] = " + obj.getAttribute("id") ); obj = obj.parentNode; if( obj == null ) break; if( ++retry > 100 ) return; } if( obj != null ){ obj.remove(); obj = null; } return; } //複数スタックを許可するポップアップの終了条件を要素から取得 var e0 = document.querySelectorAll('div[id="' + POPUP_BLOCK + '"][' + POPUP_ENDTIME + ']'); for( var i=0; i < e0.length; i++ ){ val = e0[i].getAttribute(POPUP_ENDTIME); if( val !== null && val !== undefined ){ attrTime = Number(val); if( dt > attrTime ){ e0[0].remove(); //console.log("★popupRemoved " + dt + " / " + attrTime); }else{ flg = true; } } } if( flg ){ window.setTimeout( closePopupMessage, 100 ); } } // ================================================================================= // 固定(永続化)ポップアップを削除する時はnullチェックしてからclosePopupMessage()を // 呼ばないと引数がnullだと複数スタックのポップアップを消す動作モードになってしまう // ================================================================================= //新着積み上げ動作中のポップアップを閉じる function closePopupContinuousStart(){ if( gelm_fixedPopupContinuousStart !== null ) closePopupMessage(gelm_fixedPopupContinuousStart); gelm_fixedPopupContinuousStart = null; } function closePopupContinuousMove(){ if( gelm_fixedPopupContinuousMove !== null ) closePopupMessage(gelm_fixedPopupContinuousMove); gelm_fixedPopupContinuousMove = null; } function closePopupContinuousReturn(){ if( gelm_fixedPopupContinuousReturn !== null ) closePopupMessage(gelm_fixedPopupContinuousReturn); gelm_fixedPopupContinuousReturn = null; } function closePopupContinuousWaitStart(){ if( gelm_fixedPopupContinuousWaitStart !== null ) closePopupMessage(gelm_fixedPopupContinuousWaitStart); gelm_fixedPopupContinuousWaitStart = null; } function closePopupContinuousWaitLoop(){ if( gelm_fixedPopupContinuousWaitLoop !== null ) closePopupMessage(gelm_fixedPopupContinuousWaitLoop); gelm_fixedPopupContinuousWaitLoop = null; } function closePopupContinuousFinish(){ if( gelm_fixedPopupContinuousFinish !== null ) closePopupMessage(gelm_fixedPopupContinuousFinish); gelm_fixedPopupContinuousFinish = null; } function closePopupContinuousEnd(){ if( gelm_fixedPopupContinuousEnd !== null ) closePopupMessage(gelm_fixedPopupContinuousEnd); gelm_fixedPopupContinuousEnd = null; } function closePopupContinuousAll(flg=false){ //flg: true=即時終了 false=順次終了 var tim = 0; gi_contAfterTopMark = 0; if( ! flg ){ //新着積み上げモード関連のポップアップは順次消していく if( gelm_fixedPopupContinuousStart !== null ){ window.setTimeout( closePopupContinuousStart, ++tim * 10 ); } if( gelm_fixedPopupContinuousMove !==null ){ window.setTimeout( closePopupContinuousMove, ++tim * 10 ); } if( gelm_fixedPopupContinuousReturn !== null ){ window.setTimeout( closePopupContinuousReturn, ++tim * 10 ); } if( gelm_fixedPopupContinuousWaitStart !== null ){ window.setTimeout( closePopupContinuousWaitStart, ++tim * 10 ); } if( gelm_fixedPopupContinuousWaitLoop !== null ){ window.setTimeout( closePopupContinuousWaitLoop, ++tim * 10 ); } if( gelm_fixedPopupContinuousFinish !== null ){ window.setTimeout( closePopupContinuousFinish, ++tim * 10 ); } if( gelm_fixedPopupContinuousEnd !== null ){ window.setTimeout( closePopupContinuousEnd, gi_displayPopupCloseTimeSec * 1000 ); } }else{ closePopupContinuousStart(); closePopupContinuousMove(); closePopupContinuousReturn(); closePopupContinuousWaitStart(); closePopupContinuousWaitLoop(); closePopupContinuousFinish(); closePopupContinuousEnd(); } if( gi_idleShortTimer && gtmr_shortTimer === null ){ window.setTimeout( replaceElementsOneShot, gi_displayPopupCloseTimeSec * 1000 + 100 ); } window.setTimeout( rebuildInfoButtons, gi_displayPopupCloseTimeSec * 1000 + 200 ); } //既読マーク捜索(情報)ポップアップを閉じる function closePopupFindInfo(){ if( gelm_fixedPopupFindInfo !== null ) closePopupMessage(gelm_fixedPopupFindInfo); gelm_fixedPopupFindInfo = null; } //既読マーク捜索(ヒット数)ポップアップを閉じる function closePopupFindCount(){ if( gelm_fixedPopupFindCount !== null ) closePopupMessage(gelm_fixedPopupFindCount); gelm_fixedPopupFindCount = null; } //ボタン付きポップアップを閉じる(既読捜索モード中断) function closePopupFindContinue(){ if( gelm_fixedPopupFindContinue !== null ) closePopupMessage(gelm_fixedPopupFindContinue); gelm_fixedPopupFindContinue = null; } //ボタン付きポップアップを閉じる(既読捜索モード続行可否問い合わせ) function closePopupFindConfirm(){ if( gelm_fixedPopupFindConfirm !== null ) closePopupMessage(gelm_fixedPopupFindConfirm); gelm_fixedPopupFindConfirm = null; } //既読マーク捜索ポップアップ類を全部閉じる function closePopupFindAll(){ var tim = 0; //継続可否のポップアップは消えているはずだが closePopupFindContinue(); //ほか捜索モード関連のポップアップは順次消していく if( gelm_fixedPopupFindConfirm !== null ){ window.setTimeout( closePopupFindConfirm, ++tim * 10 ); } if( gelm_fixedPopupFindInfo !==null ){ window.setTimeout( closePopupFindInfo, ++tim * 10 ); } if( gelm_fixedPopupFindCount !== null ){ window.setTimeout( closePopupFindCount, gi_displayPopupCloseTimeSec * 1000 ); } } //新着クリア待ち中ポップアップを閉じる function closePopupClearNewTweetMessage(){ if( gelm_fixedPopupClearNewTweet !== null ) closePopupMessage(gelm_fixedPopupClearNewTweet); gelm_fixedPopupClearNewTweet = null; } //DM新着表示ポップアップを閉じる function closePopupClearNewDM(){ if( gelm_fixedPopupClearNewDM !== null ) closePopupMessage(gelm_fixedPopupClearNewDM); gelm_fixedPopupClearNewDM = null; } //先頭にスクロールのポップアップを閉じる function closePopupScrToTop(){ if( gelm_fixedScrToTop !== null ) closePopupMessage(gelm_fixedScrToTop); gelm_fixedScrToTop = null; } //次回のスクロール先頭で既読マークのポップアップを閉じる function closePopupScrTopMark(){ if( gelm_fixedScrTopMark !== null ) closePopupMessage(gelm_fixedScrTopMark); gelm_fixedScrTopMark = null; } //ボタン付きポップアップを閉じる(強制リロード問い合わせ) function closePopupReloadConfirm(){ if( gelm_fixedReloadConfirm !== null ) closePopupMessage(gelm_fixedReloadConfirm); gelm_fixedReloadConfirm = null; } /************************************************************ コンフィグ・システムコンフィグのデータ操作関連関数 ************************************************************/ //URLごとの各種設定をローカルストレージから読み込む function loadPageSettings(){ var v, idx; var u = getPageURL(); if( u == "" ) return; //連続読み込みなのでloadSetting内では読み込まない loadStorageData(); //インターバル値を一旦初期状態に戻す giA_updateIntervalMs = giA_defaultIntervalMs; v = loadSetting( INTERVAL_HEADER, u, true ); if( v !== null ){ v = Number(v); giA_updateIntervalMs[gi_dispMode] = v * 1000; gi_updateCountMs = 0; //console.log("☆loadPageSettings [" + gi_updateCountMs + "]" ); } //強制リロードまでの時間を一旦初期状態に戻す giA_reloadTimeoutSec = giA_defaultReloadTimeoutSec; v = loadSetting( RELOAD_HEADER, u, true ); if( v !== null ){ v = Number(v); giA_reloadTimeoutSec[gi_dispMode] = v; } //自動更新OFFの設定保存値を読み込む gi_modeAutoOff = gi_defaultModeAutoOff; v = loadSetting( AUTOOFF_HEADER, u, true ); if( v !== null ){ v = Number(v); if( v == 0 ){ //AUTO = ONにする gi_modeAutoOff = 0; }else{ //AUTO = OFFにする gi_modeAutoOff = 1; gi_displayPaused = 1; } } //短周期タイマの常時ON設定保存値を読み込む gi_idleShortTimer = gi_defalutIdleShortTimer; v = loadSetting( IDLETM_HEADER, u, true ); if( v !== null ){ v = Number(v); if( v == 0 ){ //ずっと動作させ続けて停止させない gi_idleShortTimer = 0; }else{ //時間がたつと停止 gi_idleShortTimer = 1; } } //手動更新禁止時間の設定保存値を読み込む gi_manualUpdateIntervalSec = gi_defaultManualUpdateIntervalSec; v = loadSetting( MANUAL_HEADER, u, true ); if( v !== null ){ v = Number(v); gi_manualUpdateIntervalSec = v; } //メディアサイズ設定を読み込む gi_mediaSize = gi_defaultMediaSize; v = loadSetting( MEDIA_HEADER, u, true ); if( v !== null ){ v = Number(v); gi_mediaSize = v; } //RT&引用RT設定を読み込む gi_notDispRt = gi_defaultNotDispRt; v = loadSetting( NOTRT_HEADER, u, true ); if( v !== null ){ v = Number(v); gi_notDispRt = v; } //メディアサイズ設定とRT非表示設定をドキュメント反映とローカル保存 updateMediaAttribute(); //Home上部の新着件数表示設定を読み込む if( gi_dispMode == MODE_HOME ){ swichDispNumberNewTweet(1); } //下部アイコン表示設定を読み込む gi_notDispCommIcon = gi_defaultNotDispCommIcon; v = loadSetting( NOTICON_HEADER, u, true ); if( v !== null ){ v = Number(v); gi_notDispCommIcon = v; } //下部アイコン表示設定をドキュメント反映とローカル保存 updateCommIconAttribute(); //ボタン毎の動作設定を読み込む for( idx=0; idx 0 ){ gelm0[0].setAttribute( gstr_scrMediaAttr, gi_mediaSize ); } v = loadSetting( MEDIA_HEADER, u, true ); if( (v === null && gi_mediaSize != gi_defaultMediaSize) || (v != null && v != gi_mediaSize) ){ saveSetting( MEDIA_HEADER, u, gi_mediaSize, true ); } //RT非表示設定をドキュメントに設定し、ローカルにも保存 switch(gi_notDispRt){ case 1: rt = 1; quote = 0; break; case 2: rt = 0; quote = 1; break; case 3: rt = 1; quote = 1; break; default: rt = 0; quote = 0; break; } //CSSで切り替わるようにRT/QUOTE非表示情報を書き込む if( gelm0.length > 0 ){ gelm0[0].setAttribute( gstr_scrNotRtAttr, rt ); gelm0[0].setAttribute( gstr_scrNotQuoteAttr, quote ); } v = loadSetting( NOTRT_HEADER, u, true ); if( (v === null && gi_notDispRt != gi_defaultNotDispRt) || (v != null && v != gi_notDispRt) ){ saveSetting( NOTRT_HEADER, u, gi_notDispRt, true ); } return; } //ツイート下部のアイコン類を非表示にする設定をドキュメントとローカルに保存 function updateCommIconAttribute(){ var v; var u = getPageURL(); if( u == "" ) return; //連続読み込み+書き込みなのでloadSetting/saveSetting内では読み込まない loadStorageData(); //CSSで切り替わるように下部アイコン非表示情報を書き込む gelm0 = document.querySelectorAll('body'); if( gelm0.length > 0 ){ gelm0[0].setAttribute( gstr_scrNotCommIconAttr, gi_notDispCommIcon ); } v = loadSetting( NOTICON_HEADER, u, true ); if( (v === null && gi_notDispCommIcon != gi_defaultNotDispCommIcon) || (v != null && v != gi_notDispCommIcon) ){ saveSetting( NOTICON_HEADER, u, gi_notDispCommIcon, true ); } } /************************************************************ コンフィグ・システムコンフィグ画面関連関数 ************************************************************/ //増減ステップ定義 const STEP_TYPE_OPACITY = 1; // 0〜100 const STEP_TYPE_FONT = 2; // 8〜24 const STEP_TYPE_WIDTH = 3; // 100〜200 const STEP_TYPE_DELAY = 4; // 100〜3000 //コンフィグのテーブル外ボタンスタイルを設定 function setConfigExtButtonStyle(obj){ //obj: 対象エレメント obj.style.fontSize = "10px"; obj.style.width = "128px"; obj.style.height = "24px"; } //コンフィグのためのエレメントを生成してオーバーレイ表示する function dispSettingMessage(){ closePopupToolTips(); var e0, e1, e2, e6, e = [], idx, nowObj, nowTime, endTime, HTML = ""; var u = getPageURL(); if( u == "" ) return; gb_changedSetting = false; HTML += CRLF + "

"; HTML += CRLF + "PseudoTweetDeck [Ver" + VERSION_INFO + "]
"; HTML += CRLF + "Config Setting
"; HTML += CRLF + "Path=" + u + "
"; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + "
"; HTML += CRLF + "
"; HTML += CRLF + ""; HTML += CRLF + ""; HTML += makeConfigSwitchValueHTML("自動更新モード","ON:通常モード
OFF:強制停止モード","ELM_AUTO_OFF_MODE"); HTML += makeConfigSwitchValueHTML("短周期タイマ","IDLE:都度停止
ALWAYS:常時動作","ELM_SHORT_IDLE_MODE"); HTML += makeConfigUpDownValueHTML((gi_dispMode != MODE_NOTI)?"自動更新間隔":"自動新着表示クリア間隔","5〜3600(sec)","ELM_INTERVAL_TIME"); HTML += makeConfigUpDownValueHTML("強制リロード間隔","0〜7200(sec)
※不使用時=0","ELM_FORCE_TIME"); HTML += makeConfigUpDownValueHTML("更新禁止期間","1〜60(sec)","ELM_HOLD_TIME"); HTML += makeConfigUpDownValueHTML("メディアサムネイルサイズ",SIZE_NAME[0] + "
" + SIZE_NAME[1] + "
" + SIZE_NAME[2] + "
" + SIZE_NAME[3] + "
" + SIZE_NAME[4],"ELM_MEDIA_SIZE"); HTML += makeConfigUpDownValueHTML("RT&引用RT表示設定",NOTRT_NAME[0] + "
" + NOTRT_NAME[1] + "
" + NOTRT_NAME[2] + "
" + NOTRT_NAME[3],"ELM_HIDE_RT"); HTML += makeConfigSwitchValueHTML("NGワード有効設定","ON:有効
OFF:無効","ELM_ENABLE_NGWORD"); HTML += makeConfigSwitchValueHTML("各ツイート下部アイコンの表示","ON:表示
OFF:非表示","ELM_DISP_COMMICON"); if( gi_dispMode == MODE_HOME ){ HTML += makeConfigSwitchValueHTML("ツイート欄の表示","ON:表示
OFF:非表示","ELM_DISP_EDIT"); HTML += makeConfigSwitchValueHTML("ツイート後にエディット欄を閉じる","ON:閉じる
OFF:閉じない","ELM_CLOSE_EDIT"); HTML += makeConfigSwitchValueHTML("先頭カラムの新着件数表示","ON:表示
OFF:非表示","ELM_DISP_NEW_TWEET"); HTML += makeConfigSwitchValueHTML("新着件数のみボタンに表示","ON:表示
OFF:非表示","ELM_DISP_NEW_COUNT"); } if( gi_dispMode != MODE_NOTI ){ HTML += makeConfigSwitchValueHTML("読込件数をボタンに表示","ON:表示
OFF:非表示","ELM_DISP_RECV_COUNT"); HTML += makeConfigUpDownValueHTML("既読マーク背景色設定","0:非表示
1〜" + READ_COLOR_CYCLE + ":表示タイプ","ELM_BGCOLOR_TYPE"); } HTML += CRLF + ""; if( gi_dispMode != MODE_NOTI ){ HTML += makeConfigSwitchValueHTML("最新記事の上に積むのを試みる動作中のポップアップ","ON:表示する
OFF:表示しない","ELM_CONTPOPUP"); HTML += makeConfigUpDownValueHTML("最新記事の上に新着を積むため遷移する待機時間","100〜3000(ms)","ELM_CONTDLY"); HTML += makeConfigUpDownValueHTML("最新記事の上に新着を積むため遷移先から戻る待機時間","100〜10000(ms)","ELM_CONTRET"); HTML += makeConfigUpDownValueHTML("最新記事の上に新着を積む時にレコード更新を待つ1回の待機時間","100〜3000(ms)","ELM_CONTDOMW"); HTML += makeConfigUpDownValueHTML("最新記事の上に新着を積む時にレコード更新を待つ回数","1〜30","ELM_CONTDOMC"); HTML += makeConfigSwitchValueHTML("既読マーク捜索動作中のポップアップ","ON:表示する
OFF:表示しない","ELM_FINDPOPUP"); HTML += makeConfigUpDownValueHTML("既読マーク捜索時のスクロール1回毎の待機時間","10〜10000(ms)","ELM_FINDINTVAL"); HTML += makeConfigSwitchValueHTML("スクロールを最上部に戻す動作中のポップアップ","ON:表示する
OFF:表示しない","ELM_SCRTOTOPPOPUP"); HTML += makeConfigSwitchValueHTML("スクロール最上部で既読マーク動作中のポップアップ","ON:表示する
OFF:表示しない","ELM_SCRTOPMKPOPUP"); } //情報表示部ボタンクリックの左右各設定 HTML += CRLF + ""; HTML += CRLF + " "; HTML += CRLF + " "; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; if( gi_dispMode != MODE_NOTI ){ HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; } if( gi_dispMode == MODE_NOTI ){ HTML += CRLF + ""; } HTML += CRLF + "
設定項目設定範囲/選択肢設定値
タイマのリセットRESET
情報表示部クリック時の動作"; HTML += CRLF + " "; HTML += CRLF + "
左(" + BTN_TXT_BTNL +")中(" + BTN_TXT_BTNM + ")右(" + BTN_TXT_BTNR + ")件数(" + BTN_TXT_BTNC + ")
" + getButtonsColumn("ELM_LABEL_BTN", 0, 7, 2, true) + "
情報表示部ボタン有効" + getButtonsColumn("ELM_ENABLE_BUTTON", 0, 3, 1) + "
スクロールを最上部に戻す" + getButtonsColumn("ELM_SCRTOTOP", 0, 7, 2) + "
短周期処理を単発実行する" + getButtonsColumn("ELM_RESSRTTMR", 0, 7, 2) + "
最新記事に既読マークする" + getButtonsColumn("ELM_AUTOMARK", 0, 7, 2) + "
手動更新トリガをかける" + getButtonsColumn("ELM_MANTRIG", 0, 7, 2) + "
手動更新時に新着を上に積むのを試みる" + getButtonsColumn("ELM_CONTNEW", 0, 7, 2) + "
既読マークを捜索して遡る" + getButtonsColumn("ELM_FINDMODE", 0, 7, 2) + "
次回のスクロール最上部で既読マーク" + getButtonsColumn("ELM_SCRTOPMK", 0, 7, 2) + "
通知ページの新着をクリアする" + getButtonsColumn("ELM_CLRNEWTW", 0, 7, 2) + "

"; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + "
"; HTML += CRLF + "

" + PSEUDO_URL + "

"; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + "
"; HTML += CRLF + "

"; //コンフィグ画面を構築 e0 = document.querySelectorAll('div[id="react-root"]'); if( e0.length > 0 ){ //設定起動中のフラグを立てる(強制リロードの回避) gb_enableSettingWindow = true; //親要素にマウスホイールを処理させない holdWheelEvents(); //背景エレメント固定部 e1 = document.createElement("div"); e1.setAttribute("id",SETTING_BLOCK); e1.style.display = "block"; e1.style.position = "fixed"; e1.style.height = "100%"; e1.style.width = "100%"; e1.style.backgroundColor = COLOR_BGCOLOR; e1.style.color = COLOR_FGCOLOR; e1.style.zIndex = "199"; setStopEvents(e1); //背景エレメントスクロール部 e2 = document.createElement("div"); e2.style.display = "flex"; e2.style.position = "relative"; e2.style.height = "100%"; e2.style.width = "100%"; e2.style.overflow = "scroll"; e2.style.justifyContent = "center"; e2.insertAdjacentHTML("beforeend", HTML); e1.appendChild(e2); e0[0].appendChild(e1); //テーブルエレメント e[0] = document.getElementById('ELM_MAIN_TABLE'); e[0].style.minWidth = DIALOG_MIN_WIDTH; e[0].style.maxWidth = DIALOG_MAX_WIDTH; e[1] = document.getElementById('ELM_INNER_TABLE'); e[1].style.fontSize = DIALOG_FONT_SIZE; //自動モード setupConfigSwitchProperty( "ELM_AUTO_OFF_MODE", gi_modeAutoOff, "OFF", "ON", u ); //短周期タイマ都度停止モード setupConfigSwitchProperty( "ELM_SHORT_IDLE_MODE", gi_idleShortTimer, "IDLE", "ALWAYS", u ); //自動更新インターバル setupConfigUpDownProperty( "ELM_INTERVAL_TIME", giA_updateIntervalMs[gi_dispMode] / 1000, 5, 3600, u ); //強制リロードインターバル setupConfigUpDownProperty( "ELM_FORCE_TIME", giA_reloadTimeoutSec[gi_dispMode], 0, 7200, u ); //更新禁止期間 setupConfigUpDownProperty( "ELM_HOLD_TIME", gi_manualUpdateIntervalSec, 1, 60, u ); //メディアサムネイルサイズ setupConfigUpDownProperty( "ELM_MEDIA_SIZE", gi_mediaSize, 0, 4, u ); //RT&引用RT非表示 setupConfigUpDownProperty( "ELM_HIDE_RT", gi_notDispRt, 0, 3, u ); //ツイート下部アイコンの表示 setupConfigSwitchProperty( "ELM_DISP_COMMICON", gi_notDispCommIcon, "OFF", "ON", u ); //NGワード有効 setupConfigSwitchProperty( "ELM_ENABLE_NGWORD", gi_enableNGWord, "ON", "OFF", u ); //情報部ボタン有効無効 for(idx=0; idx
"; HTML += CRLF + "PseudoTweetDeck Ver[" + VERSION_INFO + "]
"; HTML += CRLF + "System Config Setting
"; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + "
"; HTML += CRLF + "
"; HTML += CRLF + ""; HTML += CRLF + ""; HTML += makeConfigSwitchValueHTML("テーマカラー","DARK:ダーク/ブラック
LIGHT:ライトテーマ","ELM_COLORMODE"); HTML += makeConfigUpDownValueHTML("短周期タイマ間隔","50〜1000(ms)","ELM_SHORT_INTVL"); HTML += makeConfigUpDownValueHTML("短周期タイマを停止する経過時間","1〜30(sec)","ELM_SHORT_IDLE_TIME"); HTML += makeConfigUpDownValueHTML("短周期タイマ停止後の遅延実施回数","0〜5","ELM_SHORT_IDLE_DELAY"); HTML += makeConfigSwitchValueHTML("スクロールイベントで短周期処理を行う","ON:行う
OFF:行わない","ELM_USESCROLL_EVENT"); HTML += makeConfigUpDownValueHTML("起動待ち合わせ時間","1〜30(sec)","ELM_INIT_WAIT"); HTML += makeConfigUpDownValueHTML("スクロールを最上部に戻してからトリガまでの時間","0〜30(sec)
※無効時は0に設定","ELM_ONTOP_WAIT"); HTML += makeConfigUpDownValueHTML("強制リロード開始までのラグ時間","100〜10000(ms)","ELM_RELOAD_WAIT"); HTML += makeConfigUpDownValueHTML("強制リロード禁止時間","10〜300(sec)","ELM_LOCK_TIME"); HTML += makeConfigUpDownValueHTML("ポップアップ表示時間","0〜30(sec)
※無効時は0に設定","ELM_POPUP_TIME"); HTML += makeConfigUpDownValueHTML("情報表示部+ボタン不透明度","0〜100(%)
透明〜不透明","ELM_DSP_OPACITY"); HTML += makeConfigUpDownValueHTML("情報表示部+ボタン枠幅","100〜200(px)","ELM_INFOWIDTH"); HTML += makeConfigUpDownValueHTML("情報表示部+ボタン枠高","10〜30(px)","ELM_INFOHEIGHT"); HTML += makeConfigUpDownValueHTML("情報表示部テキストフォントサイズ","8〜24(px)","ELM_FONTTEXT"); HTML += makeConfigUpDownValueHTML("情報表示部ボタンフォントサイズ","8〜24(px)","ELM_FONTBTN"); HTML += makeConfigUpDownValueHTML("新着・受信件数表示位置","0:非表示 1:左 2:中央 3:右","ELM_COUNT_POSITION"); HTML += makeConfigSwitchValueHTML("ショートカットキーを無効にする","ON:無効にする
OFF:無効にしない","ELM_DIS_KEYEVENT"); HTML += makeConfigSwitchValueHTML("タイムスタンプの置換","ON:絶対時間に置換
OFF:相対時間のまま","ELM_CHG_TIME_MODE"); HTML += makeConfigSwitchValueHTML("新着表示を自動でクリックする","ON:クリックする
OFF:クリックしない","ELM_CLICK_NEW"); HTML += makeConfigSwitchValueHTML("更新直後に新着表示を自動でクリックする","ON:クリックする
OFF:クリックしない","ELM_MANCLICK_NEW"); HTML += makeConfigSwitchValueHTML("レコード更新時間を自動更新OFFでも表示する","ON:表示する
OFF:表示しない","ELM_ENABLE_DOM"); HTML += makeConfigSwitchValueHTML("フォーカスのあるタブでもカウントダウンを非表示にする","ON:非表示にする
OFF:表示する","ELM_NOCOUNTDOWN"); HTML += makeConfigSwitchValueHTML("同一の記事を並べない","HIDE:重複は非表示
DISP:重複でも表示する","ELM_NODISP_SAME"); HTML += makeConfigSwitchValueHTML("画像サムネイル左クリックで別タブに表示","ON:表示する
OFF:表示しない","ELM_IMAGE_NEWTAB"); HTML += makeConfigSwitchValueHTML("画像表示時まず原寸で試す","ON:原寸で試し次に大サイズで開く
OFF:常に大サイズで開く","ELM_IMAGE_TRYORG"); HTML += makeConfigSwitchValueHTML("情報表示部とボタンのヘルプToolTips表示","ON:表示する
OFF:表示しない","ELM_HELP_POPUP"); HTML += makeConfigSwitchValueHTML("既読ポイントを表示","ON:表示する
OFF:表示しない","ELM_READ_CHECK"); HTML += makeConfigUpDownValueHTML("既読チェックボックス有効時の不透明度","0〜100(%)
透明〜不透明","ELM_CHKEN_OPACITY"); HTML += makeConfigUpDownValueHTML("既読チェックボックス無効時の不透明度","0〜100(%)
透明〜不透明","ELM_CHKDI_OPACITY"); HTML += makeConfigUpDownValueHTML("既読ポイント数","4〜100","ELM_READ_COUNT"); HTML += makeConfigSwitchValueHTML("既読ポイント背景の繰り返しパターン","TOP:パターン以降先頭要素で繰り返し
ALL:パターン全体を繰り返す","ELM_BGCYCLE"); HTML += makeConfigSwitchValueHTML("検索ページのタブタイトル表記を短縮する","ON:短縮する
OFF:短縮しない","ELM_SEATITLE"); HTML += makeConfigSwitchValueHTML("検索ページで更新が掛からない環境でトリガ時CSSを無効にする","ON:無効にする
OFF:無効にしない","ELM_SEACSS"); HTML += makeConfigUpDownValueHTML("検索ページで更新が掛からない環境でトリガ時CSSを無効にする追加待ち時間","0〜5000(ms)","ELM_SEACSSW"); HTML += CRLF + "
設定項目設定範囲/選択肢設定値

"; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + "" HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + "
"; HTML += CRLF + "

" + PSEUDO_URL + "
"; HTML += CRLF + "

"; HTML += CRLF + "※システムコンフィグの設定項目は全タブ共通なので変更後は全てリロードして下さい"; HTML += CRLF + "
"; HTML += CRLF + ""; if(DEBUG_MODE){ HTML += CRLF + ""; }else{ HTML += CRLF + ""; } HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + "
"; HTML += CRLF + "
"; //システムコンフィグ画面を構築 e0 = document.querySelectorAll('div[id="react-root"]'); if( e0.length > 0 ){ //設定起動中のフラグを立てる(強制リロードの回避) gb_enableSettingWindow = true; //親要素にマウスホイールを処理させない holdWheelEvents(); //背景エレメント固定部 e1 = document.createElement("div"); e1.setAttribute("id",SETTING_BLOCK ); e1.style.display = "block"; e1.style.position = "fixed"; e1.style.height = "100%"; e1.style.width = "100%"; e1.style.backgroundColor = COLOR_BGCOLOR; e1.style.color = COLOR_FGCOLOR; e1.style.zIndex = "199"; setStopEvents(e1); //背景エレメントスクロール部 e2 = document.createElement("div"); e2.style.display = "flex"; e2.style.position = "relative"; e2.style.height = "100%"; e2.style.width = "100%"; e2.style.justifyContent = "center"; e2.style.overflow = "scroll"; e2.insertAdjacentHTML("beforeend", HTML); e1.appendChild(e2); e0[0].appendChild(e1); //テーブルエレメント e[0] = document.getElementById('ELM_MAIN_TABLE'); e[0].style.minWidth = DIALOG_MIN_WIDTH; e[0].style.maxWidth = DIALOG_MAX_WIDTH; e[1] = document.getElementById('ELM_INNER_TABLE'); e[1].style.fontSize = DIALOG_FONT_SIZE; //カラーモード setupConfigSwitchProperty( "ELM_COLORMODE", COLOR_MODE, "DARK", "LIGHT", KEY_SYSTEM ); //短周期タイマインターバル setupConfigUpDownProperty( "ELM_SHORT_INTVL", gi_shortIntervalMs, 50, 1000, KEY_SYSTEM ); //短周期タイマ一時停止時間 setupConfigUpDownProperty( "ELM_SHORT_IDLE_TIME", Math.floor(gi_shortTimerIdleMs / 1000), 1, 30, KEY_SYSTEM ); //短周期タイマ停止後のワンショット実行回数 setupConfigUpDownProperty( "ELM_SHORT_IDLE_DELAY", gi_shortTimerIdleDelayCount, 0, 5, KEY_SYSTEM ); //スクロールイベントで短周期処理を行う setupConfigSwitchProperty( "ELM_USESCROLL_EVENT", gi_useScrollEvent, "ON", "OFF", KEY_SYSTEM ); //起動待ち合わせ時間 setupConfigUpDownProperty( "ELM_INIT_WAIT", Math.floor(gi_initWaitMs / 1000), 1, 30, KEY_SYSTEM ); //スクロールをトップに戻してからトリガまでの時間 setupConfigUpDownProperty( "ELM_ONTOP_WAIT", Math.floor(gi_onTopWaitMs / 1000), 0, 30, KEY_SYSTEM ); //強制リロードまでのラグ時間 setupConfigUpDownProperty( "ELM_RELOAD_WAIT", gi_reloadWaitMs, 100, 10000, KEY_SYSTEM ); //連続リロード禁止時間 setupConfigUpDownProperty( "ELM_LOCK_TIME", gi_forceUpdateLockTimeSec, 10, 300, KEY_SYSTEM ); //ポップアップ表示時間 setupConfigUpDownProperty( "ELM_POPUP_TIME", gi_displayPopupCloseTimeSec, 0, 30, KEY_SYSTEM ); //表示部+ボタンの不透明度 setupConfigUpDownProperty( "ELM_DSP_OPACITY", Math.floor(gf_dispUnitOpacity * 100), 0, 100, KEY_SYSTEM, STEP_TYPE_OPACITY ); //表示部+ボタンの幅 setupConfigUpDownProperty( "ELM_INFOWIDTH", (DISPINFO_WIDTH).replace("px",""), 100, 200, KEY_SYSTEM, STEP_TYPE_WIDTH ); //表示部+ボタンの高さ setupConfigUpDownProperty( "ELM_INFOHEIGHT", (DISPINFO_HEIGHT).replace("px",""), 10, 30, KEY_SYSTEM ); //表示部テキストフォントサイズ setupConfigUpDownProperty( "ELM_FONTTEXT", (gstrA_titleSize[0]).replace("px",""), 8, 24, KEY_SYSTEM ); //表示部ボタンフォントサイズ setupConfigUpDownProperty( "ELM_FONTBTN", (gstrA_buttonSize[0]).replace("px",""), 8, 24, KEY_SYSTEM ); //タイムスタンプ置換 setupConfigSwitchProperty( "ELM_CHG_TIME_MODE", gi_replaceTimeStamp, "ON", "OFF", KEY_SYSTEM ); //新着を自動的に押す setupConfigSwitchProperty( "ELM_CLICK_NEW", gi_autoClickNewTweet, "ON", "OFF", KEY_SYSTEM ); //更新直後の新着を自動的に押す setupConfigSwitchProperty( "ELM_MANCLICK_NEW", gi_manualUpdateTriggerNewTweet, "ON", "OFF", KEY_SYSTEM ); //DOM時間を自動更新OFFでも表示する setupConfigSwitchProperty( "ELM_ENABLE_DOM", gi_enableDomTimeAutoOff, "ON", "OFF", KEY_SYSTEM ); //カウントダウンを非表示にする setupConfigSwitchProperty( "ELM_NOCOUNTDOWN", gi_noCountDownDisp, "ON", "OFF", KEY_SYSTEM ); //同一のRT記事を表示しない setupConfigSwitchProperty( "ELM_NODISP_SAME", gi_notDispSameArticle, "HIDE", "DISP", KEY_SYSTEM ); //画像サムネイル左クリックで別タブに表示する setupConfigSwitchProperty( "ELM_IMAGE_NEWTAB", gi_displayImageNewTab, "ON", "OFF", KEY_SYSTEM ); //画像サムネイル左クリックで別タブに表示する時origで試す setupConfigSwitchProperty( "ELM_IMAGE_TRYORG", gi_displayImageTryOrig, "ON", "OFF", KEY_SYSTEM ); //情報表示部ボタンのヘルプToolTipsを表示する setupConfigSwitchProperty( "ELM_HELP_POPUP", gi_dispToolTipsPopup, "ON", "OFF", KEY_SYSTEM ); //新着・受信件数表示の表示位置 setupConfigUpDownProperty( "ELM_COUNT_POSITION", gi_countPosition, BTN4_POSITION_NONE, BTN4_POSITION_RIGHT, KEY_SYSTEM ); //ショートカットキーの無効化 setupConfigSwitchProperty( "ELM_DIS_KEYEVENT", gi_disableKeyEvent, "ON", "OFF", KEY_SYSTEM ); //既読マークのチェックボックスを出すか setupConfigSwitchProperty( "ELM_READ_CHECK", gi_enableReadPointCheckBox, "ON", "OFF", KEY_SYSTEM ); //既読マークチェックボックス有効時の不透明度 setupConfigUpDownProperty( "ELM_CHKEN_OPACITY", Math.floor(CHECKBOX_ENABLE_OPACITY * 100), 0, 100, KEY_SYSTEM, STEP_TYPE_OPACITY ); //既読マークチェックボックス無効時の不透明度 setupConfigUpDownProperty( "ELM_CHKDI_OPACITY", Math.floor(CHECKBOX_DISABLE_OPACITY * 100), 0, 100, KEY_SYSTEM, STEP_TYPE_OPACITY ); //既読ポイント数 setupConfigUpDownProperty( "ELM_READ_COUNT", gi_readArticles, 4, 100, KEY_SYSTEM ); //既読マークの背景の繰り返しパターン setupConfigSwitchProperty( "ELM_BGCYCLE", READ_COLOR_CYCLEMODE, "ALL", "TOP", KEY_SYSTEM ); //検索ページでタブタイトルを短縮する setupConfigSwitchProperty( "ELM_SEATITLE", gi_searchPageShortTitle, "ON", "OFF", KEY_SYSTEM ); //検索ページで更新トリガが掛からない環境の時トリガ時だけCSSを無効にする setupConfigSwitchProperty( "ELM_SEACSS", gi_disableCssOnSearchUpdate, "ON", "OFF", KEY_SYSTEM ); //検索ページで更新トリガが掛からない環境の時トリガ時だけCSSを無効にする追加待ち時間 setupConfigUpDownProperty( "ELM_SEACSSW", gi_disableCssSearchWaitMs, 0, 5000, KEY_SYSTEM ); //全保存データの削除 e[0] = document.getElementById('ELM_ALL_CLEAR'); setConfigExtButtonStyle(e[0]); e[0].onclick = function(e){e.stopPropagation(); deleteAllData(); return false;}; //各ページ保存データの削除 e[0] = document.getElementById('ELM_URLS_CLEAR'); setConfigExtButtonStyle(e[0]); e[0].onclick = function(e){e.stopPropagation(); deleteAllPageSetting(); return false;}; //既読ポイントの削除 e[0] = document.getElementById('ELM_READ_CLEAR'); setConfigExtButtonStyle(e[0]); e[0].onclick = function(e){e.stopPropagation(); deleteReadPointData(); return false;}; //NGワードの編集 e[0] = document.getElementById('ELM_NGWORD_OPEN1'); setConfigExtButtonStyle(e[0]); e[0].onclick = function(e){ e.stopPropagation(); closeSettingWindow(true); dispSystemNGWordWindow(); return false; }; e[0] = document.getElementById('ELM_NGWORD_OPEN2'); setConfigExtButtonStyle(e[0]); e[0].onclick = function(e){ e.stopPropagation(); closeSettingWindow(true); dispSystemNGWordWindow(); return false; }; //システムエクスポート e[0] = document.getElementById('ELM_SYS_EXPORT'); setConfigExtButtonStyle(e[0]); e[0].onclick = function(e){ e.stopPropagation(); loadStorageData(); var tmp = JSON.stringify(gobj_localData); window.prompt(" 全データのエクスポート\r\n テキスト全体をコピーしてテキストエディタで保存して下さい。", tmp); return false; }; //システムインポート e[0] = document.getElementById('ELM_SYS_IMPORT'); setConfigExtButtonStyle(e[0]); e[0].onclick = function(e){ e.stopPropagation(); var inp = window.prompt(" 全データのインポート\r\n 他のタブを全て閉じるか休止してから\r\n テキスト全体をペーストして下さい。\r\n (※現在の設定は全てクリアされて上書きされます)", ""); var obj = null; if( inp !== null && inp !== undefined ){ //前後の改行・タブ文字・余白を削除 inp = inp.trim(); inp = inp.replace(/^[\s| ]+|[\s| ]+$/g,""); }else{ inp = ""; } if( inp.length > 0 && inp.substring(0,1) == "{" && inp.slice(-1) == "}" ){ obj = JSON.parse(inp); if( typeof obj == "object" ){ gobj_localData = JSON.parse(JSON.stringify(obj)); saveStorageData(); if( window.confirm(" システム設定を保存しました\r\n リロードしますか?") == false ) return false; window.location.reload(); } } return false; }; //デバッグ表示 e[0] = document.getElementById('ELM_DEBUG'); setConfigExtButtonStyle(e[0]); e[0].onclick = function(e){ e.stopPropagation(); if( DEBUG_MODE ){ e.target.value = "DEBUG ON"; }else{ e.target.value = "DEBUG OFF"; } debugSetting(); return false; }; //コンフィグ画面を開く e[0] = document.getElementById('ELM_CONFIG_PAGE'); setConfigExtButtonStyle(e[0]); e[0].onclick = function(e){ e.stopPropagation(); closeSettingWindow(false); dispSettingMessage(); return false; }; //設定画面を閉じる e[0] = document.getElementById('ELM_CLOSE'); setConfigExtButtonStyle(e[0]); e[0].onclick = function(e){e.stopPropagation(); closeSettingWindow(true); return false;}; } } //ボタンタグ文字列の生成 function getButtonsColumn(id, min, max, len, isLabel=false){ //id: エレメントID基本部 //min: エレメント数値部最小値 //max: エレメント数値部最大値 //len: エレメント数値部桁数 ※最大5桁 //isLabel: 見出し行=true, それ以外=false //return: ボタンタグ文字列 var ret = ""; for( var i=min; i " } ret = ret.trim(); return ret; } //コンフィグ・システムコンフィグのHTML部を生成する(ON/OFF項目) function makeConfigSwitchValueHTML(title,valtext,tag){ //title: 設定項目名 //valtext: 値の説明文字列 //tag: タグの識別ID //return: 生成されたHTML var HTML = ""; HTML += CRLF + ""; HTML += CRLF + " " + title + ""; HTML += CRLF + " " + valtext + ""; HTML += CRLF + " "; HTML += CRLF + ""; return HTML; } //コンフィグ・システムコンフィグのHTML部を生成する(増減項目) function makeConfigUpDownValueHTML(title,valtext,tag){ //title: 設定項目名 //valtext: 値の説明文字列 //tag: タグの識別ID //return: 生成されたHTML var HTML = ""; HTML += CRLF + ""; HTML += CRLF + " " + title + ""; HTML += CRLF + " " + valtext + ""; HTML += CRLF + " "; HTML += CRLF + " "; HTML += CRLF + " "; HTML += CRLF + ""; return HTML; } //コンフィグ・システムコンフィグ項目のプロパティとイベントを登録(ON/OFF項目) function setupConfigSwitchProperty(tag,val,onText,offText,u,btnWidth="95%"){ var e0 = document.getElementById(tag); e0.style.width = btnWidth; e0.value = ((val==1)?onText:offText); e0.setAttribute("param",val); e0.onclick = function(e){ e.stopPropagation(); var v = Number(e.target.getAttribute("param")); v = (v==1)?0:1; e.target.value = ((v==1)?onText:offText); e.target.setAttribute("param",v); saveSettingValueFromSwitch( tag, u, v ); return false; }; } //コンフィグ・システムコンフィグ項目のプロパティとイベントを登録(増減項目) function setupConfigUpDownProperty(tag,val,minVal,maxVal,u,stepType=0){ //stepType: 通常範囲最大で切り替え=0, STEP_TYPE_xxx=1〜 var e = []; e[0] = document.getElementById(tag); e[0].style.width = "50%"; e[0].style.pointerEvents = "none"; e[0].value = val; e[1] = document.getElementById(tag + "_VALUP"); e[1].style.width = "20%"; e[1].onclick = function(e){e.stopPropagation(); valueUpButton( tag, minVal, maxVal, u, stepType ); return false;}; e[2] = document.getElementById(tag + "_VALDN"); e[2].style.width = "20%"; e[2].onclick = function(e){e.stopPropagation(); valueDnButton( tag, minVal, maxVal, u, stepType ); return false;}; } /************************************************************ コンフィグ・システムコンフィグ操作関連関数 ************************************************************/ //コンフィグ数値増減テーブル const VALUES0 = [0,10,20,30,40,50,60,70,80,90,100,200,300,400,500,700,1000,1200,1500,1800,2000,2500,3000,3500,4000,4500,5000,5500,6000,6500,7000,7500,8000,8500,9000,9500,10000,11000,12000,13000,14000,15000]; const VALUES1 = [0,5,10,15,20,25,30,35,40,45,50,55,60,70,80,90,100,120,150,180,200,250,280,300,350,400,450,500,600,700,800,900,1000,1200,1500,1800,2000,2400,3000,3600,4200,4800,5600,6400,7200]; const VALUES2 = [0,5,10,15,20,25,30,35,40,45,50,55,60,70,80,90,100,120,150,180,200,250,300,350,400,450,500,600,700,800,900,1000,1200,1500,1800,2000,2400,3000,3600,4000,4500,4800,5000]; const VALUES3 = [0,50,100,110,120,130,140,150,160,170,180,190,200,210,220,230,240,250,270,300,350,400,450,500,600,700,800,900,1000]; const VALUES4 = [0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,130,140,150,160,170,180,190,200,250,300,350,400,4500,500]; const VALUES5 = [0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,130,140,150,160,170,180,190,200,210,220,230,240,250]; const VALUES6 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,22,25,27,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100]; const VALUES7 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60]; const VALUESP = [0,10,20,30,40,50,60,70,80,90,100];//OPACITY用10ステップ const VALUESW = [100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150, 152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200];//表示部横幅用2ステップ const VALUESF = [8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32];//フォントサイズ用1ステップ const VALUESD = [100,125,150,175,200,250,300,350,400,450,500,550,600,650,700,750,800,850,900,950,1000,1200,1500,1800,2000,2400,3000];//遷移用遅延時間ステップ var VALUES = []; //数値増減テーブルの選択 function selectValueTable(min,max,stepType=0){ //min: 設定最小値 //max: 設定最大値 //stepType: 通常範囲最大で切り替え=0, STEP_TYPE_xxx=1〜 if( stepType == STEP_TYPE_OPACITY ) VALUES = VALUESP;//OPACITY用10ステップ else if( stepType == STEP_TYPE_FONT ) VALUES = VALUESF;//フォントサイズ用1ステップ else if( stepType == STEP_TYPE_WIDTH ) VALUES = VALUESW;//表示部横幅用2ステップ else if( stepType == STEP_TYPE_DELAY ) VALUES = VALUESD;//遷移用遅延時間ステップ else if( max > VALUES1[VALUES1.length-1] ) VALUES = VALUES0; else if( max > VALUES2[VALUES2.length-1] ) VALUES = VALUES1; else if( max > VALUES3[VALUES3.length-1] ) VALUES = VALUES2; else if( max > VALUES4[VALUES4.length-1] ) VALUES = VALUES3; else if( max > VALUES5[VALUES5.length-1] ) VALUES = VALUES4; else if( max > VALUES6[VALUES6.length-1] ) VALUES = VALUES5; else if( max > VALUES7[VALUES6.length-1] ) VALUES = VALUES6; else VALUES = VALUES7; } //コンフィグの増ボタン共通処理 function valueUpButton(tgt, min, max, u, stepType=0){ //tgt: 対象となるエレメントID //min: 設定可能な最小値 //max: 設定可能な最大値 //u: 設定対象のURL/PATH //stepType: 通常範囲最大で切り替え=0, STEP_TYPE_xxx=1〜 selectValueTable(min,max,stepType); var e1 = document.getElementById(tgt); var val = Number(e1.value); if( val < min ) val = min; if( val > max ) val = max; for( var i=0; i max ) val = max; e1.value = val; saveSettingValueFromUpDn(tgt, u, val); break; } } } //コンフィグの減ボタン共通処理 function valueDnButton(tgt, min, max, u, stepType=0){ //tgt: 対象となるエレメントID //min: 設定可能な最小値 //max: 設定可能な最大値 //u: 設定対象のURL/PATH //stepType: 通常範囲最大で切り替え=0, STEP_TYPE_xxx=1〜 selectValueTable(min,max,stepType); var e1 = document.getElementById(tgt); var val = Number(e1.value); if( val < min ) val = min; if( val > max ) val = max; for( var i=VALUES.length; i>0; i-- ){ if( VALUES[i-1] < val && val <= VALUES[i] ){ val = VALUES[i-1]; if( val < min ) val = min; e1.value = val; saveSettingValueFromUpDn(tgt, u, val); break; } } } //ON-OFFボタンで変更した値の格納・記憶 function saveSettingValueFromSwitch(tgt, u, val){ //tgt: 対象となるエレメントID //u: 設定対象のURL/PATH //val: 設定値 var idx; switch(tgt){ case "ELM_AUTO_OFF_MODE": gi_modeAutoOff = val; //自動モードを切り替えたらタイマ類をリセット gdt_lastRecvTime = gdt_lastTriggerTime = new Date(); gi_updateCountMs = giA_updateIntervalMs[gi_dispMode] - 1000; saveSetting( AUTOOFF_HEADER, u, val ); break; case "ELM_SHORT_IDLE_MODE": gi_idleShortTimer = val; saveSetting( IDLETM_HEADER, u, val ); //どちらの設定であっても切り替えられたら短周期タイマを再開させるためワンショット replaceElementsOneShot(); break; case "ELM_DISP_COMMICON": gi_notDispCommIcon = val; updateCommIconAttribute(); break; case "ELM_ENABLE_NGWORD": gi_enableNGWord = val; saveSetting( ENABLENGWORD_HEADER, u, val ); break; case "ELM_CONTPOPUP": gi_updateContinuousDispPopup = val; saveSetting( CONTPOPUP_HEADER, u, val ); break; case "ELM_FINDPOPUP": gi_findModeDispPopup = val; saveSetting( FINDPOPUP_HEADER, u, val ); break; case "ELM_SCRTOTOPPOPUP": gi_scrToTopModeDispPopup = val; saveSetting( SCRTOTOPPOPUP_HEADER, u, val ); break; case "ELM_SCRTOPMKPOPUP": gi_scrTopMarkModeDispPopup = val; saveSetting( SCRTOPMKPOPUP_HEADER, u, val ); break; case "ELM_DISP_EDIT": gi_hideEditControl = val; swichEditColumn(); break; case "ELM_CLOSE_EDIT": gi_newTweetCompleteCloseEdit = val; saveSetting( EDITCLOSE_HEADER, u, val ); break; case "ELM_DISP_NEW_TWEET": gi_hideNumberNewTweet = val; swichDispNumberNewTweet(true); break; case "ELM_DISP_NEW_COUNT": gi_dispNumberNewTweetCount = val; saveSetting( NEWTWCOUNT_HEADER, u, val ); break; case "ELM_DISP_RECV_COUNT": gi_dispNumberRecvTweetCount = val; saveSetting( RECVTWCOUNT_HEADER, u, val ); break; case "ELM_COLORMODE": COLOR_MODE = val; saveSetting( COLORMODE_HEADER, u, val ); break; case "ELM_USESCROLL_EVENT": gi_useScrollEvent = val; saveSetting( USESCROLL_HEADER, u, val ); break; case "ELM_CHG_TIME_MODE": gi_replaceTimeStamp = val; saveSetting( CHGTIME_HEADER, u, val ); break; case "ELM_CLICK_NEW": gi_autoClickNewTweet = val; saveSetting( CLICKNEW_HEADER, u, val ); break; case "ELM_MANCLICK_NEW": gi_manualUpdateTriggerNewTweet = val; saveSetting( MANTRIGNEW_HEADER, u, val ); break; case "ELM_ENABLE_DOM": gi_enableDomTimeAutoOff = val; saveSetting( ENDOMTIME_HEADER, u, val ); break; case "ELM_NOCOUNTDOWN": gi_noCountDownDisp = val; saveSetting( NOCOUNTDN_HEADER, u, val ); break; case "ELM_NODISP_SAME": gi_notDispSameArticle = val; saveSetting( NODISPSAME_HEADER, u, val ); break; case "ELM_IMAGE_NEWTAB": gi_displayImageNewTab = val; saveSetting( IMAGENEW_HEADER, u, val ); break; case "ELM_IMAGE_TRYORG": gi_displayImageTryOrig = val; saveSetting( IMAGEORG_HEADER, u, val ); break; case "ELM_HELP_POPUP": gi_dispToolTipsPopup = val; saveSetting( HELPPOPUP_HEADER, u, val ); break; case "ELM_DIS_KEYEVENT": gi_disableKeyEvent = val; saveSetting( DISKEYEV_HEADER, u, val ); break; case "ELM_READ_CHECK": gi_enableReadPointCheckBox = val; saveSetting( READCHK_HEADER, u, val ); break; case "ELM_BGCYCLE": READ_COLOR_CYCLEMODE = val; saveSetting( BGCYCLE_HEADER, u, val ); break; case "ELM_SEATITLE": gi_searchPageShortTitle = val; saveSetting( SEATITLE_HEADER, u, val ); break; case "ELM_SEACSS": gi_disableCssOnSearchUpdate = val; saveSetting( SEACSS_HEADER, u, val ); break; } //ボタン有効無効設定(1桁の添え字つきエレメントID) switch(tgt.substr(0,tgt.length-1)){ case "ELM_ENABLE_BUTTON": idx = Number(tgt.slice(-1)); giA_enableButton[idx] = val; saveSetting( ENABLEBUTTON_HEADER[idx], u, val ); resetElements(); break; } //ボタン割り付け(2桁の添え字つきエレメントID) switch(tgt.substr(0,tgt.length-2)){ case "ELM_SCRTOTOP": idx = Number(tgt.slice(-2)); giA_scrToTopButton[idx] = val; saveSetting( SCRTOTOP_HEADER[idx], u, val ); resetElements(); break; case "ELM_RESSRTTMR": idx = Number(tgt.slice(-2)); giA_oneShotShortTimer[idx] = val; saveSetting( RESSRTTMR_HEADER[idx], u, val ); resetElements(); break; case "ELM_AUTOMARK": idx = Number(tgt.slice(-2)); giA_manualUpdateAutoCheck[idx] = val; saveSetting( AUTOMARK_HEADER[idx], u, val ); resetElements(); break; case "ELM_CLRNEWTW": idx = Number(tgt.slice(-2)); giA_clearNewNotification[idx] = val; saveSetting( CLRNEWTW_HEADER[idx], u, val ); resetElements(); break; case "ELM_MANTRIG": idx = Number(tgt.slice(-2)); giA_manualUpdateTrigger[idx] = val; saveSetting( MANTRIG_HEADER[idx], u, val ); resetElements(); break; case "ELM_CONTNEW": idx = Number(tgt.slice(-2)); giA_updateContinuousButton[idx] = val; saveSetting( CONTNEW_HEADER[idx], u, val ); resetElements(); break; case "ELM_FINDMODE": idx = Number(tgt.slice(-2)); giA_findReadPointButton[idx] = val; saveSetting( FINDMODE_HEADER[idx], u, val ); resetElements(); break; case "ELM_SCRTOPMK": idx = Number(tgt.slice(-2)); giA_scrTopMarkButton[idx] = val; saveSetting( SCRTOPMK_HEADER[idx], u, val ); resetElements(); break; } //リロードを促すダイアログを表示するためにフラグを立てる gb_changedSetting = true; } //増減ボタンで変更した値の格納・記憶 function saveSettingValueFromUpDn(tgt, u, val){ //tgt: 対象となるエレメントID //u: 設定対象のURL/PATH //val: 設定値 var i; switch(tgt){ case "ELM_INTERVAL_TIME": giA_updateIntervalMs[gi_dispMode] = val * 1000; saveSetting( INTERVAL_HEADER, u, val ); //インターバルが変更されたのでカウンタリセット gdt_lastRecvTime = gdt_lastTriggerTime = new Date(); gi_updateCountMs = giA_updateIntervalMs[gi_dispMode] - 1000; break; case "ELM_FORCE_TIME": giA_reloadTimeoutSec[gi_dispMode] = val; saveSetting( RELOAD_HEADER, u, val ); break; case "ELM_HOLD_TIME": gi_manualUpdateIntervalSec = val; saveSetting( MANUAL_HEADER, u, val ); break; case "ELM_MEDIA_SIZE": gi_mediaSize = val; updateMediaAttribute(); break; case "ELM_HIDE_RT": gi_notDispRt = val; updateMediaAttribute(); break; case "ELM_BGCOLOR_TYPE": //既読マーク背景の定義は -1, 0, 1,... なのでインデックスを1つずらす gi_readCheckedColorMode = val - 1; rclickReadPoint(false,true); break; case "ELM_READ_COUNT": gi_readArticles = val; saveSetting( READCOUNT_HEADER, KEY_SYSTEM, val ); break; case "ELM_SHORT_INTVL": gi_shortIntervalMs = val; saveSetting( SHORTINTVL_HEADER, KEY_SYSTEM, val ); break; case "ELM_SHORT_IDLE_TIME": //短周期タイマを一時停止させる設定は秒で編集するのでミリ秒に戻す gi_shortTimerIdleMs = val * 1000; saveSetting( IDLESHORT_HEADER, KEY_SYSTEM, (val * 1000) ); break; case "ELM_SHORT_IDLE_DELAY": gi_shortTimerIdleDelayCount = val; saveSetting( IDLEDELAY_HEADER, KEY_SYSTEM, val ); break; case "ELM_INIT_WAIT": //起動時待ち合わせ時間は秒で編集するのでミリ秒に戻す gi_initWaitMs = val * 1000; saveSetting( INITWAIT_HEADER, KEY_SYSTEM, (val * 1000) ); break; case "ELM_ONTOP_WAIT": //スクロールをトップに戻したあとのトリガまでの時間は秒で編集するのでミリ秒に戻す gi_onTopWaitMs = val * 1000; saveSetting( ONTOPWAIT_HEADER, KEY_SYSTEM, (val * 1000) ); break; case "ELM_RELOAD_WAIT": gi_reloadWaitMs = val; saveSetting( RELOADWAIT_HEADER, KEY_SYSTEM, val ); break; case "ELM_LOCK_TIME": gi_forceUpdateLockTimeSec = val; saveSetting( LOCKTIME_HEADER, KEY_SYSTEM, val ); break; case "ELM_POPUP_TIME": gi_displayPopupCloseTimeSec = val; saveSetting( POPUPTIME_HEADER, KEY_SYSTEM, val ); break; case "ELM_DSP_OPACITY": gf_dispUnitOpacity = Number(val) / 100.0; //opacity0.0〜1.0を0〜100で設定しているので小数に戻す saveSetting( HDOPACITY_HEADER, KEY_SYSTEM, (Number(val)/100.0) ); break; case "ELM_CHKEN_OPACITY": CHECKBOX_ENABLE_OPACITY = Number(val) / 100.0; //opacity0.0〜1.0を0〜100で設定しているので小数に戻す saveSetting( CHKENAOP_HEADER, KEY_SYSTEM, (Number(val)/100.0) ); break; case "ELM_CHKDI_OPACITY": //opacity0.0〜1.0を0〜100で設定しているので小数に戻す CHECKBOX_DISABLE_OPACITY = Number(val) / 100.0; saveSetting( CHKDISOP_HEADER, KEY_SYSTEM, (Number(val)/100.0) ); break; case "ELM_INFOWIDTH": DISPINFO_WIDTH = val + "px"; saveSetting( INFOWIDTH_HEADER, KEY_SYSTEM, val + "px" ); break; case "ELM_INFOHEIGHT": DISPINFO_HEIGHT = val + "px"; saveSetting( INFOHEIGHT_HEADER, KEY_SYSTEM, val + "px" ); break; case "ELM_FONTTEXT": for(i=0; i 0 ){ e0[0].remove(); } //親要素にマウスホイールを処理させないのを解除 releaseWheelEvents(); //設定起動中のフラグを落とす(強制リロードの回避終了) gb_enableSettingWindow = false; if(withReload && gb_changedSetting){ if( window.confirm("  システム設定を保存しました\r\n  リロードしますか?") == false ) return; window.location.reload(); } console.log("closeSettingWindow: Setting="); console.dir(gobj_localData); gf_lockDispLocalStorage = false; } /************************************************************ ヘルプ画面表示関連関数 ************************************************************/ //ヘルプ・設定情報表示ウィンドウ表示 function dispInfoDialog(){ closePopupToolTips(); var i, idx; var aut = (gi_modeAutoOff) ? "ON" : "OFF"; var sht = (gi_idleShortTimer) ? "OFF" : "ON"; var rth = Math.floor(giA_reloadTimeoutSec[gi_dispMode] / 3600); var rtm = Math.floor(giA_reloadTimeoutSec[gi_dispMode] % 3600 / 60); var rts = giA_reloadTimeoutSec[gi_dispMode] % 60; var rtt = ("0" + rth).slice(-2) + ":" + ("0" + rtm).slice(-2) + ":" + ("0" + rts).slice(-2); var reb = (giA_reloadTimeoutSec[gi_dispMode]) ? rtt : "----"; var siz = window.innerWidth + "x" + window.innerHeight; var ntf = (gi_dispMode == MODE_NOTI) ? true : false; var msg = ""; msg += SPC + "------------------------------------"; if(!ntf){ msg += SPC + "自動更新インターバル = " + giA_updateIntervalMs[gi_dispMode] / 1000 + "(sec)"; msg += SPC + "手動更新操作の禁止期間 = " + gi_manualUpdateIntervalSec + "(sec)"; msg += SPC + "自動更新の強制停止モード = " + aut; } msg += SPC + "短周期タイマ常時稼動モード = " + sht; msg += SPC + "更新受信最終時刻 = " + toFormatedTimeString(gdt_lastRecvTime); msg += SPC + "強制再起動までの待機時間 = " + reb; msg += SPC + "メディアサムネイルの表示 = " + SIZE_NAME[gi_mediaSize]; msg += SPC + "RT&引用RTの表示設定"; msg += SPC + "   = " + NOTRT_NAME[gi_notDispRt]; if( gi_dispMode == MODE_HOME ){ msg += SPC + "上部新着件数の表示設定 = " + ( (gi_hideNumberNewTweet) ? "OFF" : "ON" ); } msg += SPC + "TabSize = " + siz; for( i=0; i -1 ){ msg += SPC + "チェックボックス : ColorType=[" + gi_readCheckedColorMode + "]"; }else{ msg += SPC + "チェックボックス : 非表示"; } msg += SPC + "  : 左クリック=" + gi_readArticles + "件を既読マーク"; msg += SPC + "  : 右クリック=既読マーク背景色切替"; } if( gi_dispMode == MODE_HOME ){ msg += SPC + BTN_TXT_ED0 + "/" + BTN_TXT_ED1; msg += SPC + " : 左クリック=ツイート入力欄表示切り替え"; msg += SPC + " : 右クリック=上部の新着件数表示切り替え"; } msg += SPC + "------------------------------------"; if(!ntf){ msg += SPC + "[COUNT / DOM時刻] , "; } msg += SPC + "[Latest / DOM時刻] :"; if(!ntf){ msg += SPC + "   緑:自動更新トリガ有効"; msg += SPC + "   黄:自動更新トリガ直前"; msg += SPC + "   赤:自動更新トリガ発行中"; if( ! gi_enableDomTimeAutoOff ){ msg += SPC + "[Paused Refresh] :"; }else{ msg += SPC + "[Paused / DOM時刻] :"; } msg += SPC + "   青:自動更新停止中"; }else{ msg += SPC + "   緑:(通知ページは常時自動動作)"; } msg += SPC + "表示内容に依存しない色替 :"; msg += SPC + "   水:手動更新の抑制期間中"; msg += SPC + "   紫:強制リロード直前"; msg += SPC + "------------------------------------"; msg += SPC + BTN_TXT_INT + "(明色) / " + BTN_TXT_HLP + "(暗色) :"; msg += SPC + "   基本色は情報表示部に準ずる"; msg += SPC + BTN_TXT_SRT + " :"; msg += SPC + "  短周期タイマ都度停止中"; msg += SPC + "   基本色は情報表示部に準ずる"; msg += SPC + "   灰:短周期タイマ停止中"; msg += SPC + "  短周期タイマ常時稼動中"; msg += SPC + "   基本色は情報表示部に準ずる"; if(!ntf){ msg += SPC + BTN_TXT_AUT + " :"; msg += SPC + "  自動更新の通常動作中"; msg += SPC + "   基本色は情報表示部に準ずる"; msg += SPC + "  自動更新の強制停止中"; msg += SPC + "   灰:自動更新強制停止中"; } msg += SPC + "------------------------------------"; dispHelpInfoDialogWindow(msg); } //情報表示ダイアログ(既読ポイント情報) function dispReadDialog(){ closePopupToolTips(); if( ! gi_enableReadPointCheckBox || gi_readArticles < 0 || gi_dispMode == MODE_NOTI ) return; var idx, dsp=0; var msg = ""; msg += SPC + "------------------------------------"; msg += SPC + "既読ポイント数 : " + gi_readArticles; if( gi_readCheckedColorMode > -1 ){ msg += SPC + "表示タイプ : " + Number(gi_readCheckedColorMode + 1) + " / " + READ_COLOR_CYCLE; }else{ msg += SPC + "表示タイプ : 非表示中"; } msg += SPC + "------------------------------------"; for( idx = 0; idx < gi_readArticles; idx++ ){ if( gstrA_readArticleURL[idx] != "" ){ msg += SPC + "既読ポイント" + Number(idx + 1) + ":(" + gstrA_readTimeStamp[idx] + ")"; msg += SPC + gstrA_readArticleURL[idx]; msg += SPC + "------------------------------------"; dsp++; }} if( dsp == 0 ){ msg += SPC + "現在既読ポイントは設定されていません"; msg += SPC + "------------------------------------"; } dispHelpInfoDialogWindow(msg); } //ヘルプ・情報表示ウィンドウの表示処理共通部 function dispHelpInfoDialogWindow(msg, buttonCenter=false){ //msg: 表示する文字列 //buttonCenter: true=閉じるボタンを左に出す var e0, e1, e2, e3, e4, e5, e6, nowObj, nowTime, endTime, HTML = ""; var u = getPageURL(); if( u == "" ) return; var max = (DIALOG_MAX_WIDTH).replace("px","") - 8; var min = (DIALOG_MIN_WIDTH).replace("px","") - 8; var w1 = (window.innerWidth > max ) ? max : ((window.innerWidth < min ) ? min : Math.floor(window.innerWidth * 0.98)); HTML += CRLF + "

"; HTML += CRLF + "PseudoTweetDeck [Ver" + VERSION_INFO + "]
"; HTML += CRLF + "Help & Information
"; HTML += CRLF + "Path=" + u + "
"; HTML += CRLF + "
"; HTML += CRLF + ""; HTML += CRLF + ""; HTML += CRLF + "
"; HTML += CRLF + msg; HTML += CRLF + "
"; HTML += CRLF + "

" + PSEUDO_URL + "
"; if( ! buttonCenter ){ HTML += CRLF + "

"; }else{ HTML += CRLF + "

"; } HTML += CRLF + "
"; //ヘルプ表示画面を構築 e0 = document.querySelectorAll('div[id="react-root"]'); if( e0.length > 0 ){ //設定起動中のフラグを立てる(強制リロードの回避) gb_enableSettingWindow = true; //親要素にマウスホイールを処理させない holdWheelEvents(); //背景エレメント e1 = document.createElement("div"); e1.setAttribute("id",SETTING_BLOCK); e1.style.display = "block"; e1.style.position = "fixed"; e1.style.height = "100%"; e1.style.width = "100%"; e1.style.backgroundColor = COLOR_BGCOLOR; e1.style.color = COLOR_FGCOLOR; e1.style.zIndex = "299"; setStopEvents(e1); e2 = document.createElement("div"); e2.style.display = "flex"; e2.style.position = "relative"; e2.style.height = "100%"; e2.style.width = "100%"; e2.style.justifyContent = "center"; e2.style.overflow = "scroll"; e2.insertAdjacentHTML("beforeend", HTML); e1.appendChild(e2); e0[0].appendChild(e1); //テーブルエレメント e3 = document.getElementById('ELM_MAIN_TABLE'); e3.style.minWidth = DIALOG_MIN_WIDTH; e3.style.maxWidth = DIALOG_MAX_WIDTH; e4 = document.getElementById('ELM_INNER_TABLE'); e4.style.fontSize = DIALOG_FONT_SIZE; //ヘルプ画面を閉じる e5 = document.getElementById('ELM_CLOSE'); e5.style.width = "128px"; e5.onclick = function(e){e.stopPropagation(); closeSettingWindow(false); return false;}; } } /************************************************************ NGワード操作関連関数 ************************************************************/ //NGワード処理 function execNGfilter(){ //NGワード判定 if( gi_enableNGWord && gobjA_NG_all.length > 0 ){ document.querySelectorAll('main div[data-testid="cellInnerDiv"]:not([' + gstr_scrNGAttr + ']):has(article[data-testid="tweet"])').forEach(function(e) { var flg1, flg2, flg3, flgAll; var ng, user; var debug1, debug2, debug3; //ツイート本文の取得 var a = e.querySelectorAll('div[data-testid="tweetText"]'); //ツイートアカウントの取得 var b = e.querySelectorAll('div[data-testid="User-Name"] > div:nth-of-type(2) span'); //RTの場合のRTをしたアカウントの取得 var c = e.querySelectorAll('article[data-testid="tweet"]:has(.r-1iusvr4.r-16y2uox path[d^="M4.75 3.79l4.603 4.3-1.706"]) a[href]'); if( (a.length > 0 || b.length > 0 ) && e.style.display != "none" ){ //ツイート本文 var txt = ""; if( a.length > 0 ) txt = a[0].innerText + ""; //ツイートのユーザーアカウント名 (@username) var txt2 = ""; if( b.length > 0 ) txt2 = b[0].innerText + ""; //RTしたユーザーアカウント名 (/username) var txt3 = ""; if( c.length > 0 ) txt3 = c[0].getAttribute("href") + ""; flgAll = false; for( var i=0; i -1 ){ var ar = gobjA_NG_all[i].split(NG_SEP_STR); if( ar.length != 2 ){ ng = gobjA_NG_all[i]; user = ""; }else{ ng = ar[0]; user = ar[1]; } }else{ ng = gobjA_NG_all[i]; user = ""; } //本文の一致 if( ng !== null && ng !== undefined && ng != "" ){ var idx = ng.lastIndexOf("/"); if( ng.indexOf("/") == 0 && idx > 2 ){ //正規表現タイプ var pattern = ng.substring(1,idx); var flags = ng.substr(idx+1); var reg = new RegExp( pattern, flags ); if( reg.test(txt) ){ flg1 = true; debug1 = "NG type RegExp [ /" + pattern + "/" + flags + "]"; } }else{ //テキストタイプ if( txt.indexOf(ng) != -1 ){ flg1 = true; debug1 = "NG type txt [" + ng + "]"; } } } //アカウント名の一致 if( user !== null && user !== undefined && user != "" ){ user = user.toLowerCase().replace("@",""); txt2 = txt2.toLowerCase().replace("@",""); if( user == txt2 ){ flg2 = true; debug2 = "NG account [" + user + "]"; } //アカウント名がRTしたものと一致 txt3 = txt3.toLowerCase().replace("/",""); if( user == txt3 ){ flg3 = true; debug3 = "RT account [" + user + "]"; } } //NGワードのみ設定された場合、NGアカウント名のみ設定された場合、NGワード+NGアカウント名が設定された場合、NGアカウントのRTが設定された場合 if( flg1 && ng != "" && user == "" || flg2 && ng == "" && user != "" || flg1 && flg2 && ng != "" && user != "" || flg3 && (ng == NG_RT_STR || ng == NG_RT_STR2) && user != "" ){ flgAll = true; var msg = ("replaceElements : " + debug1 + " " + debug2 + " " + debug3).replace(/ /g," ").replace(/ /g," "); dispDebugTextWithTime( msg ); break; } } if( flgAll ){ e.style.display = "none"; e.setAttribute(gstr_scrNGAttr,"1"); } } }); } } //ページ別のNGワード管理ウィンドウを開く function dispPageNGWordWindow(){ var u = getPageURL(); if( u == "" ) return; dispNGWordWindow(u); } //全ページ共通のNGワード管理ウィンドウを開く function dispSystemNGWordWindow(){ dispNGWordWindow(KEY_SYSTEM); } //NGワード管理ウィンドウの表示 function dispNGWordWindow(u){ //u: デコード済みURLPATH もしくは SYSTEM var e, e6, msg = "", e0, e1, e2, e3; closeSettingWindow(false); if( u == KEY_SYSTEM ){ //システム共通のNGワードを読み込んでURL個別のNGワードとマージする gobjA_NG_system = loadSetting( NGWORDDATA_HEADER, KEY_SYSTEM ); resetNGWord(); } gb_enableSettingWindow = true; //親要素にマウスホイールを処理させない holdWheelEvents(); var i; var max = (DIALOG_MAX_WIDTH).replace("px","") - 8; var min = (DIALOG_MIN_WIDTH).replace("px","") - 8; var h0 = (window.innerHeight - 12) + "px"; var w1 = (window.innerWidth > max ) ? max : ((window.innerWidth < min ) ? min : Math.floor(window.innerWidth * 0.98)); var w2 = (window.innerWidth > max ) ? "65" : ((window.innerWidth < min ) ? "57" : Math.floor(window.innerWidth * 0.16)); var color_bg = COLOR_BGCOLOR; var color_base = COLOR_BASE; //スクロール位置が先頭に戻ったら既読マークをする処理中のポップアップ表示 msg += "
" msg += ""; msg += "
"; msg += "
PseudoTweetDeck Ver[" + VERSION_INFO + "]
"; msg += "NG Word Setting [" + (( u == KEY_SYSTEM ) ? ("システム共通NGワード編集") : ("ページ個別NGワード編集")) + "]
"; if( u == KEY_SYSTEM ){ msg += "全ページ共通の定義

"; }else{ msg += "path = [ " + u + " ]用の定義

"; } msg += "

"; msg += ""; //ここに可変部が差し込まれる msg += "

"; msg += "
"; msg += "

"; msg += "

"; msg += "

"; msg += ""; msg += ""; msg += ""; msg += ""; msg += "

"; if( u === KEY_SYSTEM ){ msg += "※共通NGデータ編集後は他のタブではリロードもしくは共通NGデータ編集画面を開くか適当な画面に遷移しないと反映されません"; } msg += "

"; //NGワード編集画面を構築 e0 = document.querySelectorAll('div[id="react-root"]'); if( e0.length > 0 ){ //設定起動中のフラグを立てる(強制リロードの回避) gb_enableSettingWindow = true; //親要素にマウスホイールを処理させない holdWheelEvents(); //背景エレメント e1 = document.createElement("div"); e1.setAttribute("id",SETTING_BLOCK ); e1.style.display = "block"; e1.style.position = "fixed"; e1.style.height = "100%"; e1.style.width = "100%"; e1.style.backgroundColor = COLOR_BGCOLOR; e1.style.color = COLOR_FGCOLOR; e1.style.zIndex = "199"; setStopEvents(e1); e2 = document.createElement("div"); e2.style.display = "flex"; e2.style.position = "relative"; e2.style.height = "100%"; e2.style.width = "100%"; e2.style.justifyContent = "center"; e2.style.overflow = "scroll"; e2.insertAdjacentHTML("beforeend", msg); e1.appendChild(e2); e0[0].appendChild(e1); //ウィンドウ自体の属性 e = document.getElementById('NGWORD_WINDOW'); if( e !== null ){ e.style.minWidth = DIALOG_MIN_WIDTH; e.style.maxWidth = DIALOG_MAX_WIDTH; e.style.zIndex = "399"; setStopEvents(e); } } //可変部構築 updateNGWordWindow(u); //エクスポートボタン e = document.getElementById('ELM_BTN_EXPORT'); if( e !== null ){ e.onclick = function(){ var dat = ( u === KEY_SYSTEM ) ? gobjA_NG_system : gobjA_NG_page; var msg = ( u === KEY_SYSTEM ) ? ("[ システム共通 ]") : ("[ path = " + u + " ]"); var exp = JSON.stringify(dat); window.prompt(" " + msg + "\r\n NGワードのエクスポート\r\n テキスト全体をコピーしてテキストエディタで保存して下さい。", exp); }; } //インポートボタン e = document.getElementById('ELM_BTN_IMPORT'); if( e !== null ){ e.onclick = function(){ var obj = null; var dat = ( u === KEY_SYSTEM ) ? gobjA_NG_system : gobjA_NG_page; var msg = ( u === KEY_SYSTEM ) ? ("[ システム共通 ]") : ("[ path = " + u + " ]"); var inp = window.prompt(" " + msg + "\r\n NGワードのインポート\r\n テキスト全体をペーストして下さい。\r\n (※現在の設定はクリアされて上書きされます)", ""); if( inp !== null && inp !== undefined ){ //前後の改行・タブ文字・余白を削除 inp = inp.trim(); inp = inp.replace(/^[\s| ]+|[\s| ]+$/g,""); }else{ inp = ""; } if( inp.length > 0 && inp.substring(0,1) == "[" && inp.slice(-1) == "]" ){ obj = JSON.parse(inp); if( Array.isArray(obj) ){ if( u === KEY_SYSTEM ){ gobjA_NG_system = JSON.parse(JSON.stringify(obj)); saveSetting( NGWORDDATA_HEADER, u, gobjA_NG_system ); }else{ gobjA_NG_page = JSON.parse(JSON.stringify(obj)); saveSetting( NGWORDDATA_HEADER, u, gobjA_NG_page ); } resetNGWord(); updateNGWordWindow(u); } } }; } //個別←→共通の切り替えボタン e = document.getElementById('ELM_NG_SWITCH'); if( e !== null ){ e.onclick = function(){ window.setTimeout( switchNGWordPage, 0, u );}; } //閉じるボタン e = document.getElementById('ELM_NG_CLOSE'); if( e !== null ){ e.onclick = function(){ window.setTimeout( closeNGWordWindow, 10 );}; } } //ページNGワード定義画面と共通NGワード定義画面を切り替える function switchNGWordPage(u){ //u: デコード済みURLPATH もしくは SYSTEM var newpage; if( u == KEY_SYSTEM ){ newpage = getPageURL(); if(newpage == "") return; }else{ newpage = KEY_SYSTEM; } closeNGWordWindow(); window.setTimeout( dispNGWordWindow, 10, newpage ); } //データを読み込んで表示を更新する function updateNGWordWindow(u){ //u: デコード済みURLPATH もしくは SYSTEM var msg = "", i, btn; var recs = ( u == KEY_SYSTEM ) ? gobjA_NG_system : gobjA_NG_page; var e = document.getElementById('ELM_NG_TABLE'); if( e === null ) return; msg += "TYPE"; msg += "TEXT/PATTERN"; msg += "USER"; msg += "ACTION"; //msg += "path=" + u + "---"; for( i=0; i -1 ){ var ar = recs[i].split(NG_SEP_STR); if( ar.length != 2 ){ txt = recs[i]; user = ""; }else{ txt = ar[0]; user = ar[1]; } }else{ txt = recs[i]; user = ""; } var rectype; var idx = txt.lastIndexOf("/"); if( txt.indexOf("/") == 0 && idx > 2 ){ /* var pattern = recs[i].substring(1,idx); var flags = recs[i].substr(idx+1); var reg = new RegExp( pattern, flags ); */ rectype = "RegExp"; }else if( txt != "" ){ rectype = "Text"; }else{ rectype = "----"; } if( (txt == NG_RT_STR || txt == NG_RT_STR2) && user != "" ){ rectype = "RT@User"; } msg += "" + rectype + ""; msg += "" + txt + ""; msg += "" + user + ""; msg += " "; } msg += ""; e.innerHTML = msg; for( i=0; i -1 ){ ar = recs[idx].split(NG_SEP_STR); if( ar.length == 2 ){ txt = ar[0]; user = ar[1]; }else{ txt = recs[idx]; user = ""; } }else{ txt = recs[idx]; user = ""; } ret1 = window.prompt(" NGワードの編集\r\n アカウントのRT非表示はNGワードに\r\n 「" + NG_RT_STR + "」か「" + NG_RT_STR2 + "」を指定", txt); ret2 = window.prompt(" NGアカウントの編集", user); }else{ ret1 = window.prompt(" NGワードの追加\r\n アカウントのRT非表示はNGワードに\r\n 「" + NG_RT_STR + "」か「" + NG_RT_STR2 + "」を指定", txt); ret2 = window.prompt(" NGアカウントの追加", ""); } if( ret1 == null || ret1 == undefined ){ ret1 = ""; } if( ret2 == null || ret2 == undefined ){ ret2 = ""; } if( ret1.indexOf(NG_SEP_STR) > -1 || ret2.indexOf(NG_SEP_STR) > -1 ){ window.alert(" " + NG_SEP_STR + "は予約語なので登録出来ません"); return; } if( (ret1 == NG_RT_STR || ret1 == NG_RT_STR2) && ret2 == "" ){ window.alert(" RT非表示指定の「" + NG_RT_STR + "」\r\n はアカウントの入力が必要です"); return; } if( ret1 != "" ){ //前後の改行・タブ文字・余白を削除 ret1 = ret1.trim(); ret1 = ret1.replace(/^[\s| ]+|[\s| ]+$/g,""); } if( ret2 != "" ){ //前後の改行・タブ文字・余白・@を削除 ret2 = ret2.trim(); ret2 = ret2.replace(/^[\s| ]+|[\s| ]+$/g,""); ret2 = ret2.toLowerCase().replace("@",""); } if( ret1 == "" && ret2 == "" ) return; if( e !== null ){ if( ret2 != "" ){ recs[idx] = ret1 + NG_SEP_STR + ret2; }else{ recs[idx] = ret1; } }else{ if( ret2 != "" ){ recs.push( ret1 + NG_SEP_STR + ret2 ); }else{ recs.push( ret1 ); } } saveSetting( NGWORDDATA_HEADER, u, recs ); resetNGWord(); updateNGWordWindow(u); } //NGワードレコードの削除 function deleteNGWord( u, e ){ //u: デコード済みURLPATH もしくは SYSTEM //e: イベントオブジェクト var recs = ( u == KEY_SYSTEM ) ? gobjA_NG_system : gobjA_NG_page; var idx, ret; idx = Number((e.target.id + "").replace("ELM_BTN_DEL","")); ret = window.confirm(" NGワードの削除\r\n " + recs[idx]); if( ret ){ recs.splice(idx,1); saveSetting( NGWORDDATA_HEADER, u, recs ); resetNGWord(); updateNGWordWindow(u); } } //システムNGワードと個別NGワードを結合する function resetNGWord(){ gobjA_NG_all = [].concat(gobjA_NG_system,gobjA_NG_page); if( gi_idleShortTimer && gtmr_shortTimer === null && gi_initComplete == 1 ){ replaceElementsOneShot(); } } //NGワードウィンドウを閉じる function closeNGWordWindow(){ //親要素にマウスホイールを処理させないのを解除 releaseWheelEvents(); gb_enableSettingWindow = false; closeSettingWindow(false); } /************************************************************ メンテナンス関連関数 ************************************************************/ //ローカル保存データの全削除 function deleteAllData(){ if( window.confirm("  自動更新スクリプトが保存した\r\n  全設定データ・保存データを初期化しますか?\r\n  ※削除後にリロードが必要になります") == false ) return; var idx; var imax = window.localStorage.length; var keys; var removeCount = 0; for( idx = imax - 1; idx > -1; idx-- ){ keys = "" + window.localStorage.key(idx); if( keys == LOCAL_DATA_KEY || keys == FORCEUPDATE_HEADER || keys.indexOf("PTD_") == 0 ){ window.localStorage.removeItem(keys); removeCount++; } } if( removeCount > 0 ){ window.alert("  データを削除しました\r\n  リロードします"); window.location.reload(); }else{ window.alert("  該当データはありませんでした"); } } //既読ポイントのみクリア function deleteReadPointData(){ if( window.confirm("  自動更新スクリプトが保存した\r\n  全既読ポイントデータを初期化しますか?") == false ) return; var removeCount = 0; loadStorageData(); for( var item in gobj_localData ){ for( var i=0; i < 100; i++ ){ var obj = gobj_localData[item]; if( obj[READ_HEADER[i]] !== null && obj[READ_HEADER[i]] !== undefined ){ delete obj[READ_HEADER[i]]; removeCount++; } if( obj[READTM_HEADER[i]] !== null && obj[READTM_HEADER[i]] !== undefined ){ delete obj[READTM_HEADER[i]]; removeCount++; } } } saveStorageData(); window.alert("  " + removeCount + "件のデータを削除しました\r\n  各タブをリロードして下さい"); } //表示中ページの設定のみクリア function deletePageSetting(){ var u = getPageURL(); if( u == "" ) return; loadStorageData(); if( window.confirm("  [" + u + "]\r\n  このURL用の設定データを初期化しますか?\r\n  ※削除後にリロードが必要になります") == false ) return; if( gobj_localData[u] !== null && gobj_localData[u] !== undefined ){ delete gobj_localData[u]; saveStorageData(); window.alert("  データを削除しました\r\n  リロードします"); window.location.reload(); } } //各URLごとのデータを順次クリア function deleteAllPageSetting(){ loadStorageData(); for( var item in gobj_localData ){ if( item != KEY_SYSTEM ){ if( window.confirm("  [" + item + "]\r\n  このURL用の設定データを初期化しますか?") == true ){ delete gobj_localData[item]; } } } saveStorageData(); } //旧ローカルデータキーからの置換処理 function convertOldData(){ const CHGTABLE = [ "DispEditControl","HideEditControl","OLD_KEY1","NEW_KEY1" ]; var removeCount = 0; loadStorageData(); var value; for( var item in gobj_localData ){ for( var subitem in gobj_localData[item] ){ for( var i=0; i max ) ? max : ((window.innerWidth < min ) ? min : Math.floor(window.innerWidth * 0.98)); var w2 = (window.innerWidth > max ) ? "65" : ((window.innerWidth < min ) ? "57" : Math.floor(window.innerWidth * 0.16)); msg += "
" msg += ""; msg += "
"; msg += ""; msg += " "; msg += " "; msg += " "; msg += " "; msg += " "; msg += " "; msg += ""; msg += " "; msg += " "; msg += " "; msg += " "; msg += " "; msg += " "; msg += "
"; msg += "
"; msg += "
"; msg += "
"; msg += "
"; gelm_debugDialog = dispPopupMessage(msg, -1, COLOR_WHITE, COLOR_BLACK, true, false, false, true); e = document.getElementById('DEBUG_WINDOW'); if( e !== null ){ e.style.minWidth = DIALOG_MIN_WIDTH; e.style.maxWidth = DIALOG_MAX_WIDTH; setStopEvents(e); e.onmousewheel = function(e){ //親要素にマウスホイールを処理させない holdWheelEvents(); //既に発行されているタイマを解除 if( tmrHoldScroll !== null ){ window.clearTimeout(tmrHoldScroll); } tmrHoldScroll = window.setTimeout( function(){ //親要素にマウスホイールを処理させない処理の解除 releaseWheelEvents(); tmrHoldScroll = null; }, 1000 ); }; } //閉じる e = document.getElementById('ELM_DEBUG_BTN1'); if( e !== null ){ e.onclick = function(){ debugWindowSize = 0; saveSetting( DEBUG_WINDOW_SIZE, u, 0 ); window.setTimeout( closeDebugWindow, 10 ); }; } //クリア e = document.getElementById('ELM_DEBUG_BTN2'); if( e !== null ){ e.onclick = function(){window.setTimeout( clearDebugText, 10 );}; } //ローカルストレージ内容の展開表示 e = document.getElementById('ELM_DEBUG_BTN3'); if( e !== null ){ e.onclick = function(){window.setTimeout( dispLocalStorageData, 10 );}; } //デバッグウィンドウの高さ小 e = document.getElementById('ELM_DEBUG_BTN4'); if( e !== null ){ e.onclick = function(){ var elm = document.getElementById('DEBUG_WINDOW'); if( elm === null ) return; debugWindowSize = 1; elm.style.minHeight = elm.style.maxHeight = DEBUG_MIN_HEIGHT[debugWindowSize]; saveSetting( DEBUG_WINDOW_SIZE, u ,debugWindowSize ); }; } //デバッグウィンドウの高さ中 e = document.getElementById('ELM_DEBUG_BTN5'); if( e !== null ){ e.onclick = function(){ var elm = document.getElementById('DEBUG_WINDOW'); if( elm === null ) return; debugWindowSize = 2; elm.style.minHeight = elm.style.maxHeight = DEBUG_MIN_HEIGHT[debugWindowSize]; saveSetting( DEBUG_WINDOW_SIZE, u ,debugWindowSize ); }; } //デバッグウィンドウの高さ大 e = document.getElementById('ELM_DEBUG_BTN6'); if( e !== null ){ e.onclick = function(){ var elm = document.getElementById('DEBUG_WINDOW'); if( elm === null ) return; debugWindowSize = 3; elm.style.minHeight = elm.style.maxHeight = DEBUG_MIN_HEIGHT[debugWindowSize]; saveSetting( DEBUG_WINDOW_SIZE, u ,debugWindowSize ); }; } //デバッグウィンドウの高さ最大 e = document.getElementById('ELM_DEBUG_BTN7'); if( e !== null ){ e.onclick = function(){ var elm = document.getElementById('DEBUG_WINDOW'); if( elm === null ) return; debugWindowSize = 4; elm.style.minHeight = elm.style.maxHeight = DEBUG_MIN_HEIGHT[debugWindowSize]; saveSetting( DEBUG_WINDOW_SIZE, u ,debugWindowSize ); }; } //表示内容の全選択+クリップボードにコピー e = document.getElementById('ELM_DEBUG_BTN8'); if( e !== null ){ e.onclick = function(){ var elm = document.getElementById('DEBUG_TEXT_TABLE'); //rangeオブジェクトの作成 var range = document.createRange(); //取得した要素の内側を範囲とする range.selectNodeContents(elm); //範囲を選択状態にする window.getSelection().addRange(range); //クリップボードにコピー window.setTimeout(function(){document.execCommand('copy');}, 100); //選択を解除 window.setTimeout(function(){window.getSelection().removeAllRanges();}, 200); }; } //共通NGワードの編集 e = document.getElementById('ELM_DEBUG_BTN9'); if( e !== null ){ e.onclick = function(){ //NG-ALL dispNGWordWindow(KEY_SYSTEM); }; } //ページNGワードの編集 e = document.getElementById('ELM_DEBUG_BTN10'); if( e !== null ){ e.onclick = function(){ var u = getPageURL(); if( u == "" ) return; //NG-PAGE dispNGWordWindow( u ); }; } //トレースログ表示フィルタ e = document.getElementById('ELM_DEBUG_BTN11'); if( e !== null ){ e.onclick = function(){ dispDebugFilterWindow(u); }; } //テストボタン e = document.getElementById('ELM_DEBUG_BTN0'); if( e !== null ){ e.onclick = function(){ //汎用のテストボタン TEST_FUNC(); }; } } //デバッグウィンドウにテキストを表示 function dispDebugText(txt="", timestamp="", errLevel=LOG_NORM){ if( ! DEBUG_MODE ) return; var e = document.getElementById(ELM_DEBUG_TEXT); const TEXT = "TEXT"; const TIME = "TIME"; const TYPE = "TYPE"; var i, tmp = "", errFont1 = "", errFont2 = "", typeStr = ""; //先頭に積む if( txt != "" ){ if( debugTextArray.length > 0 && (debugTextArray[0][TEXT]).indexOf(txt) != -1 ){ debugTextArray[0][TIME] = timestamp; debugTextArray[0][TEXT] = txt; debugTextArray[0][TYPE] = errLevel; }else{ debugTextArray.unshift({TIME:timestamp,TEXT:txt,TYPE:errLevel}); if( debugTextArray.length > MAX_DEBUG_RECS ){ debugTextArray.pop(); } } } if( e === null ) return; tmp = ""; for( i=0; i"; errFont2 = ""; typeStr = debugLogHidden[debugTextArray[i][TYPE]]; if( debugTextArray[i][TIME] != "" ){ tmp += ""; tmp += ""; tmp += "" ; }else{ tmp += "" ; } } } tmp += "
" + errFont1 + "[" + debugTextArray[i][TIME] + "]" + errFont2 + "" + typeStr + "" + errFont1 + debugTextArray[i][TEXT] + errFont2 + "
" + errFont1 + debugTextArray[i][TEXT] + errFont2 + "
"; e.textContent = ""; e.insertAdjacentHTML("beforeend", tmp); } //デバッグウィンドウに時刻付きでテキストを表示 function dispDebugTextWithTime(txt, err=LOG_NORM){ if( ! DEBUG_MODE ) return; var dt = new Date(); // dispDebugText(txt, toFormatedDateString(dt), err); dispDebugText(txt, toFormatedTimeString(dt), err); } //ローカルストレージデータを展開表示 function dispLocalStorageData(){ if( ! DEBUG_MODE ) return; if( gf_lockDispLocalStorage ) return; gf_lockDispLocalStorage = true; var max = (DIALOG_MAX_WIDTH).replace("px","") - 8; var min = (DIALOG_MIN_WIDTH).replace("px","") - 8; var w1 = (window.innerWidth > max ) ? max : ((window.innerWidth < min ) ? min : Math.floor(window.innerWidth * 0.98)); var msg = ""; loadStorageData(); var txt = JSON.stringify(gobj_localData, null, 2); console.log("LocalStorage=" + txt); msg = "
" + txt + "
"; msg += "

"; dispHelpInfoDialogWindow(msg, true); var e = document.getElementById('ELM_DEL_SETTING'); if( e !== null ){ e.onclick = deleteSettingByKey; } } //キーを指定してローカルストレージのレコードを削除 function deleteSettingByKey(){ var tmp = window.prompt(" 保存データの削除 (ex「SYSTEM,DEBUG_Mode」) \r\n PATH/SYSTEMとキーをカンマ区切りで入力"); if( tmp == null || tmp == undefined || tmp == "" ) return; var key = tmp.split(","); if( key.length == 2 ){ removeSetting( key[1], key[0] ); } } //デバッグ表示と蓄積レコードを破棄 function clearDebugText(){ if( ! DEBUG_MODE ) return; debugTextArray = []; dispDebugText(); } //トレース表示フィルタ設定ウィンドウの表示 function dispDebugFilterWindow(u){ //u: デコード済みURLPATH var i, e, e0, e1, e2, e3, e6, msg = ""; var color_bg = COLOR_BGCOLOR; var color_base = COLOR_BASE; closeSettingWindow(false); gb_enableSettingWindow = true; //親要素にマウスホイールを処理させない holdWheelEvents(); var max = (DIALOG_MAX_WIDTH).replace("px","") - 8; var min = (DIALOG_MIN_WIDTH).replace("px","") - 8; var h0 = (window.innerHeight - 12) + "px"; var w1 = (window.innerWidth > max ) ? max : ((window.innerWidth < min ) ? min : Math.floor(window.innerWidth * 0.98)); var w2 = (window.innerWidth > max ) ? "65" : ((window.innerWidth < min ) ? "57" : Math.floor(window.innerWidth * 0.16)); msg += "
" msg += ""; msg += "
"; msg += "
PseudoTweetDeck Ver[" + VERSION_INFO + "]
"; msg += "Trace Filter Setting
"; msg += "path = [ " + u + " ]用の定義

"; msg += "

"; msg += ""; //可変部 for( i=0; i" + debugFilterText[i] + ""; msg += ""; } //可変部 msg += "
"; msg += "

"; msg += ""; msg += ""; msg += ""; msg += ""; msg += "

"; msg += "

"; //フィルタ画面を構築 e0 = document.querySelectorAll('div[id="react-root"]'); if( e0.length > 0 ){ //設定起動中のフラグを立てる(強制リロードの回避) gb_enableSettingWindow = true; //親要素にマウスホイールを処理させない holdWheelEvents(); //背景エレメント e1 = document.createElement("div"); e1.setAttribute("id",SETTING_BLOCK ); e1.style.display = "block"; e1.style.position = "fixed"; e1.style.height = "100%"; e1.style.width = "100%"; e1.style.backgroundColor = COLOR_BGCOLOR; e1.style.color = COLOR_FGCOLOR; e1.style.zIndex = "199"; setStopEvents(e1); e2 = document.createElement("div"); e2.style.display = "flex"; e2.style.position = "relative"; e2.style.height = "100%"; e2.style.width = "100%"; e2.style.justifyContent = "center"; e2.style.overflow = "scroll"; e2.insertAdjacentHTML("beforeend", msg); e1.appendChild(e2); e0[0].appendChild(e1); //ウィンドウ自体の属性 e = document.getElementById('FILTER_WINDOW'); if( e !== null ){ e.style.minWidth = DIALOG_MIN_WIDTH; e.style.maxWidth = DIALOG_MAX_WIDTH; e.style.zIndex = "399"; setStopEvents(e); } for( i=0; i 0 ) return; var msg = ""; dispDebugWindow(atStart); dispDebugText(msg); } //DEBUGボタンでの各種実験 function TEST_FUNC(){ // saveDebugData(); } /************************************************************ メイン処理 ************************************************************/ dispDebugTextWithTime("Start PseudoTwDk", LOG_SYS); function startMain(){ //初期処理の完了待ち if( gi_initComplete == 0 ){ window.setTimeout(startMain, gi_shortIntervalMs); //console.log("★startMain : WaitFor initComplete"); dispDebugTextWithTime("startMain : Wait for initComplete"); return; } //更新処理開始 window.setInterval(updateTimeline, gi_timerIntervalMs); //デバッグトレース用のウィンドウを表示 if( DEBUG_MODE ) window.setTimeout( debugFunction, 10, true ); dispDebugTextWithTime("startMain : Start CountDownTimer"); } function initMain(){ //強制リロードまでの時間管理のため起動した時間を記録 saveSetting(FORCEUPDATE_HEADER, KEY_SYSTEM, ( toFormatedDateString(new Date())) ); //旧形式からコンバート convertOldData(); //システム設定の読み込み loadSystemSettings(); //背景色テーブルの初期化 setupBgColorTables(); //初期処理の遅延実行 window.setTimeout(clearElements, gi_initWaitMs); window.setTimeout(startMain, gi_initWaitMs + 10); console.log("START PseudoTwDk: Setting="); console.dir(gobj_localData); }