PageSourceSearch

https://www2.myjcom.jp/special/common/js/jcom_api.js

js myjcom.jp collected 2026-10-01 10:27:41 UTC 112,894 bytes, 3,496 lines download raw bytes

1/*--------------------------------------------------------------
2
3	jcom_api.js for API2019
4	2025/7/29	更新
5	
6--------------------------------------------------------------*/
7// stage時はapiもstageを参照するための判定
8var isStage = (location.hostname.match(/stage-www2/)) ? true : false;
9isStage = false; //	ステージも公開APIを参照する 2018/10/15
10var isMyjcom = (location.hostname.match(/www2.myjcom.jp/) || location.hostname.match(/myjcom.weska.me/)) ? true : false;
11var api_php_path = "/special/common/js/api.php?"; //  2019年版API用
12var jsonpCallbackUID = 0;
13
14/*--------------------------------------------------------------
15	2019/4/8
16	リクエストURLを作成
17--------------------------------------------------------------*/
18function getAPIRequestQuery(searchObj,flag){
19	var query = "";
20	for(var key in searchObj){
21		var val = searchObj[key];
22		if(key == 'query'){
23			if(flag){
24			val = val.replace(/ /g,'+');
25			val = val.replace(/ /g,'+');
26			}else{
27			val = encodeURIComponent(val);
28			}
29		}
30		if(key != 'keyword') query += "&"+key+"="+val;
31	}
32
33	//trace("jcom_api.js query "+query);
34	if(!flag){
35		return query;//encodeURIComponent(query)
36	}else{
37		return encodeURIComponent(query);
38	}
39}
40
41
42/*--------------------------------------------------------------
43	apiの読み込み完了 // 未実装
44--------------------------------------------------------------*/
45function jcomApiLoaded(str){
46	//trace("読み込み完了:"+str);
47	//	案件毎にoverrideして利用する。
48}
49
50/*==============================================
51	
52	2020/3/19
53	ランキングAPI
54
55	//	APIパラメータ
56	var searchObj = {
57			rankingType:1,	// 必須 ランキング種別:1(リモ録週間) 2(リモ録月間)
58			channelType:2,	// 必須 放送波種別:2(地デジ) 3(BS) 120(CATV) 200(コミュチャン)
59			genreId:3,	// 任意 ジャンルID:MINDSで定義されている親または子ジャンルIDをいずれか1種を指定可能。
60			backNumber:2,	// 任意 過去ランキング
61			limit:30,	// 任意 件数:(1〜100)
62			areaId:108,	// 任意 エリアID
63		};	
64		
65	//	制御用パラメータ
66	var statusObj = {
67			uid:0,	//	UID
68			serchTxt:['華','中国ドラマ'],//	検索結果からキーワードで絞り込む。独自実装
69			container:'.remoroku_ranking_list',		//格納コンテナ(.付きの文字列で指定)デフォルト:.ranking_list 省略可
70			noimage:'/special/common/images/no_image_800x448.jpg',		//画像がない場合の代替え画像 省略可
71			callback:'searchRankingAPIComplete',	//	コールバック関数 デフォルト:searchProgramAPIComplete 省略可
72		};	
73		
74	//	データ呼び出し
75	getJcomRankingList(searchObj,statusObj);
76	
77==============================================*/
78
79function getJcomRankingList(_searchObj,_statusObj){
80	setCurrentTimeForAPI();
81	
82	var user_area_id = jQuery.cookie("area_id");
83	if(user_area_id == undefined){
84		user_area_id = 12;
85	}
86	var searchObj = {};
87	var statusObj = {};
88	
89	// _searchObjからAPI検索用Objを抽出
90	
91	if(_searchObj.rankingType != null){
92		searchObj.rankingType = _searchObj.rankingType;
93	}
94	if(_searchObj.channelType != null){
95		searchObj.channelType = _searchObj.channelType;
96	}
97	if(_searchObj.genreId != null){
98		searchObj.genreId = _searchObj.genreId;
99	}
100	if(_searchObj.backNumber != null){
101		searchObj.backNumber = _searchObj.backNumber;
102	}
103	if(_searchObj.limit != null){
104		searchObj.limit = _searchObj.limit;
105	}
106	if(_searchObj.areaId != null){
107		searchObj.areaId = _searchObj.areaId;
108	}
109
110	
111	// _statusObjから制御用Objを抽出
112	if(_statusObj.uid != null) statusObj.uid = _statusObj.uid;
113	if(_statusObj.container != null){
114		statusObj.container = _statusObj.container;
115	}else{
116		statusObj.container = '.ranking_list';
117	}
118	if(_statusObj.container_parent != null){
119		statusObj.container_parent = _statusObj.container_parent;
120	}
121	if(_statusObj.noimage != null){
122		statusObj.noimage = _statusObj.noimage;
123	}else{
124		statusObj.noimage = '/special/common/images/no_image_800x448.jpg';
125	}
126	if(_statusObj.callback != null){
127		statusObj.callback = _statusObj.callback;
128	}else{
129		statusObj.callback = "searchRankingAPIComplete";
130	}
131	if(_statusObj.serchTxt != null){
132		statusObj.serchTxt = _statusObj.serchTxt;
133	}else{
134		statusObj.serchTxt = [];
135	}
136
137	// コールバックパラメータ名の指定
138	jsonpCallbackUID ++;
139	statusObj.jsonpCallback = 'ranking'+jsonpCallbackUID;
140
141	searchJCOMRankingAPI(searchObj,statusObj);
142}
143
144
145//	日付
146function formatDateYYYYMMDDhhmmss(str,format){
147	var yyyy = str.substr(0,4);
148	var mm = str.substr(4,2);
149	var dd = str.substr(6,2);
150	return yyyy+format[0]+mm+format[1]+dd+format[2];
151}
152function formatDateYYYYMMDDhhmmss_short(str){
153	var yyyy = str.substr(0,4);
154	var mm = Number(str.substr(4,2));
155	var dd = Number(str.substr(6,2));
156	return mm+"/"+dd;
157}
158function YYYYMMDDhhmmssToDateObj(str){
159	var yyyy = str.substr(0,4);
160	var mm = str.substr(4,2);
161	var dd = str.substr(6,2);
162	var h = str.substr(8,2);
163	var m = str.substr(10,2);
164	var s = str.substr(12,2);
165	var date = new Date(yyyy+'/'+mm+'/'+dd+' '+h+':'+m+':'+s);
166	return date;
167}
168
169
170/*--------------------------------------------------------------
171	ランキングAPI:検索
172--------------------------------------------------------------*/
173function searchJCOMRankingAPI(searchObj,statusObj){
174
175	trace('ランキングAPI(jcom_api):検索');
176	var result = [];
177	var message = "";
178	var dataType = "jsonp";
179	var jsonpCallback = statusObj.jsonpCallback;
180	var url = "https://tvguide.myjcom.jp/api/getRankingInfo/?";
181
182	trace("jsonpCallback "+jsonpCallback);
183	trace(searchObj);
184	trace(statusObj);
185
186	if(isMyjcom){
187		url += "callback=?"+getAPIRequestQuery(searchObj,false);
188		trace("ランキングAPI(jcom_api):myjcom "+url);
189	}else{
190		var param = getAPIRequestQuery(searchObj,true);
191		url = api_php_path+'wrp='+jsonpCallback+'&url='+url+param;
192		url = location.protocol+"//"+location.host+url;	// ローカルからアクセスできるよう絶対パスで指定
193		trace("ランキングAPI(jcom_api):other "+url);
194	}
195
196	var callback = statusObj.callback;
197	var load_status;
198
199	$.ajax({
200		url: url,
201		type:'POST',
202			dataType: dataType,
203		jsonpCallback: jsonpCallback
204	}).done(function(data){ // Ajaxリクエストが成功した時発動
205		trace("ランキングAPI(jcom_api):DONE");
206
207		if(data === undefined) {
208			result = ['検索失敗'];    
209			load_status = 2;
210			trace("検索失敗");
211			return;
212		}
213		
214		//		trace("======================");
215		//		trace(data);
216		load_status = data.status;
217		if(load_status != 0) return;
218		var pdata = data.RankingList;
219
220		var format_ja = ['年','月','日'];
221		var format_en = ['/','/',''];
222		var summaryFrom = formatDateYYYYMMDDhhmmss(data.summaryFrom,format_ja);
223		var summaryTo = formatDateYYYYMMDDhhmmss(data.summaryTo,format_ja);
224		var summaryFrom_en = formatDateYYYYMMDDhhmmss(data.summaryFrom,format_en);
225		var summaryTo_en = formatDateYYYYMMDDhhmmss(data.summaryTo,format_en);
226		var summaryFrom_short = formatDateYYYYMMDDhhmmss_short(data.summaryFrom);
227		var summaryTo_short = formatDateYYYYMMDDhhmmss_short(data.summaryTo);
228		statusObj.summaryFrom = summaryFrom;
229		statusObj.summaryTo = summaryTo;
230		statusObj.summaryFrom_en = summaryFrom_en;
231		statusObj.summaryTo_en = summaryTo_en;
232		statusObj.summaryFrom_short = summaryFrom_short;
233		statusObj.summaryTo_short = summaryTo_short;
234		statusObj.summaryFromOrg = data.summaryFrom;
235		statusObj.summaryToOrg = data.summaryTo;
236		var isMoreSerch = (statusObj.serchTxt.length != 0) ? true : false;
237
238		if(pdata.length != 0){
239			var rank = 1;
240			var limit = statusObj.limit;
241				
242			var nowtime = new Date();
243			nowYear = formatDate(nowtime, 'YYYY');
244			nowMonth = formatDate(nowtime, 'MM');
245			nowDay = formatDate(nowtime, 'DD');
246
247			//	APIの戻り値をNGワード処理して検索結果データを作成
248			jQuery.each(pdata, function(key, val){
249					
250					//trace(val);
251					var score = val.score;
252					var prevRank = (val.prevRank != "") ? val.prevRank : "-";
253					var programId = val.programId;
254					var title = val.title;
255					var url = val.url;
256					var photos = val.photos;
257					var defaultChannelLogoUrl = val.defaultChannelLogoUrl;
258					var channelLogoUrl = val.channelLogoUrl;
259					var channelName = val.channelName;
260					var nextBroadcast = val.nextBroadcast;
261					var warningMessage = val.warningMessage;
262					var errorCode = val.errorCode;
263					var errorMessage = val.errorMessage;
264					var status = 'DOWN';
265					
266					if(rank == prevRank){
267						status = "STAY";
268					}else if(rank < prevRank){
269						status = "UP";
270					}else if(prevRank == ""){
271						status = "NEW";
272					}
273					
274					var obj = {
275						rank:rank,
276						score:score,
277						prevRank:prevRank,
278						status:status,
279						programId:programId,
280						title:title,
281						url:url,
282						hasPhoto:false,
283						hasChannelLogo:false,
284						defaultChannelLogoUrl:defaultChannelLogoUrl,
285						channelLogoUrl:channelLogoUrl,
286						channelName:channelName,
287						warningMessage:warningMessage,
288						nextBroadcast:nextBroadcast,
289						errorCode:errorCode,
290						errorMessage:errorMessage,
291						hasNextBroadcast:false,
292						noimage:statusObj.noimage
293					};
294					
295					//	デフォルトチャンネルロゴ
296					if(defaultChannelLogoUrl){
297						obj.hasChannelLogo = true;
298					}
299
300					//	メイン写真
301					if(photos.length != 0){
302						obj.photo = photos[0].photo;
303						obj.copyright = photos[0].copyright;
304						obj.hasPhoto = true;
305					}else{
306						obj.photo = statusObj.noimage;
307						obj.copyright = "";
308					}
309					
310					//	番組情報
311					if(nextBroadcast.length != 0){
312						//	放送時間
313						var next_dateObj = YYYYMMDDhhmmssToDateObj(nextBroadcast[0].startDateTime);
314						var onairTimeObj = checkThisProgramNowOnair(next_dateObj,nextBroadcast[0].startDateTime,nextBroadcast[0].endDateTime);
315
316						obj.eid = nextBroadcast[0].eid;
317						obj.nextTitle = nextBroadcast[0].nextTitle;
318						obj.startDateTime = nextBroadcast[0].startDateTime;
319						obj.endDateTime = nextBroadcast[0].endDateTime;
320						obj.airTime = nextBroadcast[0].airTime;
321						obj.genreIds = nextBroadcast[0].genreIds;
322						obj.serviceCode = nextBroadcast[0].serviceCode;
323						obj.channelNo = nextBroadcast[0].channelNo;
324						obj.channelName = nextBroadcast[0].channelName;
325						obj.channelLogoUrl = nextBroadcast[0].channelLogoUrl;
326						obj.hasNextBroadcast = true;
327						obj.nowonair = onairTimeObj.nowonair;
328						obj.todayonair = onairTimeObj.todayonair;
329						
330					}
331
332					//	追加検索ワードで絞り込むk
333					if(isMoreSerch){
334						var isHit = false;
335						
336						var len = statusObj.serchTxt.length;
337						for(var i=0;i<len;i++){
338							var word = statusObj.serchTxt[i];
339							//if(title.indexOf(word) != -1) isHit = true;
340							if (title.includes(word)) isHit = true;
341						}//	for
342
343						if(isHit){
344							result.push(obj);
345							rank++;
346						}
347					}else{
348						result.push(obj);
349						rank++;
350					}
351						
352			});//jQuery.each
353
354		}else{
355			//    検索結果なし
356			result = ['検索結果はありません'];    
357			load_status = 1;
358		}
359	}).fail(function(data){  // Ajaxリクエストが失敗した時発動
360		result = ["APIエラー:"+data.errorMassage];    
361		load_status = 2;
362		trace("ランキングAPI(jcom_api):FAIL "+result);
363
364	}).always(function(data){  // Ajaxリクエストが成功・失敗どちらでも発動
365		trace("ランキングAPI(jcom_api):ALWAYS");
366		trace(searchObj);
367		trace(statusObj);
368		trace(data);
369
370		statusObj.api_type = 'ranking';
371		if(callback != null) parent[callback](result,load_status,searchObj,statusObj);
372	});
373
374}
375
376
377/*==============================================
378	
379	2020/3/13
380	関連番組取得API
381	getRelatedProgramInfo
382
383	//	APIパラメータ
384	var searchObj = {
385		//[01]:[02],	// [03] [04] [06] 初期値([05])	
386		tag:'これぞアメリカンホラー!,コンビの力で事件を解決!',	// 必須 関連番組タグ  初期値(-)	
387		exclude:0,	// 任意 番組除外 0(除外しない) 1(除外する) 初期値(1)	
388		sourceChannelType:3,	// 条件 検索元番組放送波 2(地上波)3(BS)120(CATV)200(コミュニティチャンネル) 初期値(-)	
389		sourceServiceCode:'29752_32295',	// 任意 検索元番組サービスコード  初期値(-)	
390		sourceEventId:40273,	// 任意 検索元番組イベントID  初期値(-)	
391		sourceProgramDate:20130911,	// 任意 検索元番組放送日  初期値(-)	
392		areaId:30,	// 必須 エリアID  初期値(-)	
393		serviceCode:'191_4,570_65406',	// 任意 サービスコード  初期値(-)	
394		genreId:'62,4',	// 任意 ジャンルID  初期値(-)	
395		since:'201702011200',	// 任意 放送日(開始)  初期値(現在日時)	
396		until:'201702811200',	// 任意 放送日(終了)  初期値(-)	
397		adult:1,	// 任意 アダルトチャンネル制御 0(含めない) 1(含める) 初期値(0)	
398		limit:50,	// 任意 最大取得件数  初期値(20)	
399
400		};	
401		
402	//	制御用パラメータ
403	var statusObj = {
404		uid:0,	//	UID
405		container:'.ranking_list',		//格納コンテナ(.付きの文字列で指定)デフォルト:.ranking_list 省略可
406		noimage:'/special/common/images/no_image_800x448.jpg',		//画像がない場合の代替え画像 省略可
407		callback:'searchRelatedProgramAPIComplete',	//	コールバック関数 デフォルト:searchRelatedProgramAPIComplete 省略可
408	};	
409		
410	//	データ呼び出し
411	getJcomRelatedProgramList(searchObj,statusObj);
412	
413==============================================*/
414
415function getJcomRelatedProgramList(_searchObj,_statusObj){
416	setCurrentTimeForAPI();
417	
418	var user_area_id = jQuery.cookie("area_id");
419	if(user_area_id == undefined){
420		user_area_id = 12;
421	}
422	var searchObj = {};
423	var statusObj = {};
424	
425	// _searchObjからAPI検索用Objを抽出
426	
427	if(_searchObj.tag != null){
428		searchObj.tag = _searchObj.tag;
429	}
430	if(_searchObj.exclude != null){
431		searchObj.exclude = _searchObj.exclude;
432	}
433	if(_searchObj.sourceChannelType != null){
434		searchObj.sourceChannelType = _searchObj.sourceChannelType;
435	}
436	if(_searchObj.sourceServiceCode != null){
437		searchObj.sourceServiceCode = _searchObj.sourceServiceCode;
438	}
439	if(_searchObj.sourceEventId != null){
440		searchObj.sourceEventId = _searchObj.sourceEventId;
441	}
442	if(_searchObj.sourceProgramDate != null){
443		searchObj.sourceProgramDate = _searchObj.sourceProgramDate;
444	}
445	if(_searchObj.areaId != null){
446		searchObj.areaId = _searchObj.areaId;
447	}else{
448		searchObj.areaId = user_area_id;
449	}
450	if(_searchObj.serviceCode != null){
451		searchObj.serviceCode = _searchObj.serviceCode;
452	}
453	if(_searchObj.genreId != null){
454		searchObj.genreId = _searchObj.genreId;
455	}
456	if(_searchObj.since != null){
457		searchObj.since = _searchObj.since;
458	}
459	if(_searchObj.until != null){
460		searchObj.until = _searchObj.until;
461	}
462	if(_searchObj.adult != null){
463		searchObj.adult = _searchObj.adult;
464	}
465	if(_searchObj.limit != null){
466		searchObj.limit = _searchObj.limit;
467	}
468
469	// _statusObjから制御用Objを抽出
470	if(_statusObj.uid != null) statusObj.uid = _statusObj.uid;
471	if(_statusObj.container != null){
472		statusObj.container = _statusObj.container;
473	}else{
474		statusObj.container = '.ranking_list';
475	}
476	if(_statusObj.container_parent != null){
477		statusObj.container_parent = _statusObj.container_parent;
478	}
479	if(_statusObj.noimage != null){
480		statusObj.noimage = _statusObj.noimage;
481	}else{
482		statusObj.noimage = '/special/common/images/no_image_800x448.jpg';
483	}
484	if(_statusObj.callback != null){
485		statusObj.callback = _statusObj.callback;
486	}else{
487		statusObj.callback = "searchRelatedProgramAPIComplete";
488	}
489
490	// コールバックパラメータ名の指定
491	jsonpCallbackUID ++;
492	statusObj.jsonpCallback = 'relationProgram'+jsonpCallbackUID;
493
494	searchJcomRelatedProgramAPI(searchObj,statusObj);
495}
496
497
498/*--------------------------------------------------------------
499	関連番組API:検索
500--------------------------------------------------------------*/
501function searchJcomRelatedProgramAPI(searchObj,statusObj){
502	trace('関連番組API(jcom_api):検索');
503	var result = [];
504	var message = "";
505	var dataType = "jsonp";
506	var jsonpCallback = statusObj.jsonpCallback;
507	var url = "https://tvguide.myjcom.jp/api/getRelatedProgramInfo/?";
508
509	trace("jsonpCallback "+jsonpCallback);
510	trace(searchObj);
511	trace(statusObj);
512
513	if(isMyjcom){
514		url += "callback=?"+getAPIRequestQuery(searchObj,false);
515		trace("関連番組API(jcom_api):myjcom "+url);
516	}else{
517	var param = getAPIRequestQuery(searchObj,true);
518		url = api_php_path+'wrp='+jsonpCallback+'&url='+url+param;
519		url = location.protocol+"//"+location.host+url;	// ローカルからアクセスできるよう絶対パスで指定
520		trace("関連番組API(jcom_api):other "+url);
521	}
522
523	var callback = statusObj.callback;
524	var load_status;
525
526	$.ajax({
527		url: url,
528		type:'POST',
529		dataType: dataType,
530		jsonpCallback: jsonpCallback
531	}).done(function(data){ // Ajaxリクエストが成功した時発動
532		trace("関連番組API(jcom_api):DONE");
533
534		if(data === undefined) {
535			result = ['検索失敗'];    
536			load_status = 2;
537			trace("検索失敗");
538			return;
539		}
540
541		//		trace("======================");
542		//		trace(data);
543		load_status = data.status;
544		totalCount = data.totalCount;
545		if(load_status != 0) return;
546		if(totalCount == 0) return;
547
548		var pdata = data.tags[0].programs;
549		trace(pdata);
550
551		if(pdata.length != 0){
552
553		var limit = statusObj.limit;
554
555		var nowtime = new Date();
556		nowYear = formatDate(nowtime, 'YYYY');
557		nowMonth = formatDate(nowtime, 'MM');
558		nowDay = formatDate(nowtime, 'DD');
559
560		//	APIの戻り値をNGワード処理して検索結果データを作成
561		jQuery.each(pdata, function(key, val){
562			var title = val.title; //	番組名
563			var startTimeOrg = val.startTime; //	放送開始日時
564			var endTimeOrg = val.endTime; //	放送終了日時
565			var airTime = val.airTime; //	放送時間
566			var programDate = val.programDate; //	放送日
567			var eventId = val.eventId; //	イベントID
568			var serviceCode = val.serviceCode; //	サービスコード
569			var channelType = val.channelType; //	放送波
570			var channelNo = val.channelNo; //	チャンネル番号
571			var channelName = val.channelName; //	チャンネル名
572			var channelLogoUrl = val.channelLogoUrl; //	チャンネルロゴファイルURL
573			var genreIds = val.genreIds; //	ジャンルID
574			var summary = val.summary; //	番組概要
575			//var url = 'https://tvguide.myjcom.jp/'+val.url; //	番組詳細URL
576			var url = val.url; //	番組詳細URL
577			var photos = val.photo; //	番組属性リスト
578
579			var date = val.startTime.slice(0,4) + '/' + val.startTime.slice(4,6) + '/' + val.startTime.slice(6,8); // 放送日yyyy/mm/ddに
580			var dateObj = new Date(date);
581			var datestr = formatDate(new Date(date), 'MM月DD日(W)');
582			var startTime = val.startTime.slice(8,10) + ':' + val.startTime.slice(10,12);
583			var endTime = val.endTime.slice(8,10) + ':' + val.endTime.slice(10,12);
584			var channel_icon_id = channel_icon[val.channelName];
585
586			var month = formatDate(dateObj, 'MM');
587			var day = formatDate(dateObj, 'DD');
588			var week = formatDate(dateObj, 'W');
589
590			var datestr_single = Number(month)+'月'+Number(day)+'日('+week+')';
591			var datestr_simple = month+'/'+day+'('+week+')';
592			var datestr_simple_single = Number(month)+'/'+Number(day)+'('+week+')';
593			var datestr_simple_single2 = Number(month)+'/'+Number(day)+'('+week+')';			
594
595			var obj = {
596				title:title,
597				startTimeOrg:startTimeOrg,
598				endTimeOrg:endTimeOrg,
599				startTime:startTime,
600				endTime:endTime,
601				airTime:airTime,
602				programDate:programDate,
603				date:datestr,
604				eventId:eventId,
605				serviceCode:serviceCode,
606				channelType:channelType,
607				channelNo:channelNo,
608				channelName:channelName,
609				channelLogoUrl:channelLogoUrl,
610				genreIds:genreIds,
611				summary:summary,
612				url:url,
613				photos:photos,
614				dateObj:dateObj,
615				datestr_single:datestr_single,
616				datestr_simple:datestr_simple,
617				datestr_simple_single:datestr_simple_single,
618				datestr_simple_single2:datestr_simple_single2,
619			};
620
621			//	メイン写真
622			if(photos.length != 0){
623				obj.photo = 'https://tvguide.myjcom.jp/'+photos[0].photo;
624				obj.copyright = photos[0].copyright;
625				obj.hasPhoto = true;
626			}else{
627				obj.photo = statusObj.noimage;
628				obj.copyright = "";
629			}
630
631				result.push(obj);
632
633
634			});//jQuery.each
635
636		}else{
637			//    検索結果なし
638			result = ['検索結果はありません'];    
639			load_status = 1;
640		}
641	}).fail(function(data){  // Ajaxリクエストが失敗した時発動
642		result = ["APIエラー:"+data.errorMassage];    
643		load_status = 2;
644		trace("関連番組API(jcom_api):FAIL "+result);
645	}).always(function(data){  // Ajaxリクエストが成功・失敗どちらでも発動
646		trace("関連番組API(jcom_api):ALWAYS");
647		trace(searchObj);
648		trace(statusObj);
649		trace(data);
650
651		searchObj.searchBtnURL = 'https://tvguide.myjcom.jp/search/event/?tag='+searchObj.tag;
652
653		statusObj.api_type = 'related';
654		if(callback != null) parent[callback](result,load_status,searchObj,statusObj);
655	});
656
657}
658
659
660
661/*==============================================
662
663	2019/2/18
664	イベントプレゼントAPI
665
666	//	APIパラメータ
667	var searchObj = {
668		title: "",
669		addKeywords: "",
670		mso: "",
671		channel: "",
672		magazine: "",
673		limit: "",
674		order: ""
675	};	
676
677	//	"displayListStartDate desc" // 新着 降順 最新が先(デフォルト、省略化)
678	//	"displayListStartDate aesc" // 新着 昇順
679	//	"displayListEndDate desc" // 閉め切り 昇順
680	//	"displayListEndDate aesc" // 閉め切り 昇順 締め切りが近い順
681
682	//	制御用パラメータ
683	var statusObj = {
684		uid:0,	//	UID
685		addCC:false,	//	リンクにccを追加するか
686		ignoreDate:false,	//	掲載開始時期前、または掲載開始時時期が未設定でも表示する(true)表示しない(false)
687		container:'.event_present_list_container',		//格納コンテナ(.付きの文字列で指定)デフォルト:.event_present_list_container 省略可
688		wrpper:'.section_present_api',		//格納セクション(.付きの文字列で指定)デフォルト:.section_present_api 省略可
689		callback:'searchProgramAPIComplete'	//	コールバック関数 デフォルト:searchProgramAPIComplete 省略可
690	};	
691
692	//	データ呼び出し
693	getJcomEventPresentList(searchObj,statusObj);
694	
695==============================================*/
696function getJcomEventPresentList(_searchObj,_statusObj){
697	trace("イベントプレゼントAPI getJcomEventPresentList");
698	setCurrentTimeForAPI();
699	
700	var searchObj = {};
701	var statusObj = {};
702	
703	// _searchObjからAPI検索用Objを抽出
704
705	if(_searchObj.limit != null){
706		statusObj.limit = _searchObj.limit;
707	}else{
708		searchObj.limit = "";
709	}
710	if(_searchObj.title != null){
711		searchObj.title = _searchObj.title;
712	}else{
713		searchObj.title = "";
714	}
715	if(_searchObj.addKeywords != null){
716		searchObj.addKeywords = _searchObj.addKeywords;
717	}else{
718		searchObj.addKeywords = "";
719	}
720	if(_searchObj.channel != null){
721		searchObj.channel = _searchObj.channel;
722	}else{
723		searchObj.channel = "";
724	}
725	if(_searchObj.mso != null){
726		searchObj.mso = _searchObj.mso;
727	}else{
728		searchObj.mso = "";
729	}
730	if(_searchObj.magazine != null){
731		searchObj.magazine = _searchObj.magazine;
732	}else{
733		searchObj.magazine = "";
734	}
735	if(_searchObj.order != null){
736		searchObj.order = _searchObj.order;
737	}else{
738		searchObj.order = "displayListStartDate desc";
739	}
740
741	// _statusObjから制御用Objを抽出
742	
743	if(_statusObj.uid != null) statusObj.uid = _statusObj.uid;
744	if(_statusObj.container != null){
745		statusObj.container = _statusObj.container;
746	}else{
747		statusObj.container = '.event_present_list_container';
748	}
749	if(_statusObj.container_parent != null){
750		statusObj.container_parent = _statusObj.container_parent;
751	}
752	if(_statusObj.callback != null){
753		statusObj.callback = _statusObj.callback;
754	}else{
755		statusObj.callback = "searchEventPresentAPIComplete";
756	}
757	if(_statusObj.addCC != null){
758		statusObj.addCC = _statusObj.addCC;
759	}else{
760		statusObj.addCC = false;
761	}
762	if(_statusObj.ignoreDate != null){
763		statusObj.ignoreDate = _statusObj.ignoreDate;
764	}else{
765		statusObj.ignoreDate = false;
766	}
767	
768	if(_statusObj.wrpper != null){
769		statusObj.wrpper = _statusObj.wrpper;
770	}else{
771		statusObj.wrpper = "section_present_api";
772	}
773	
774	/**
775	if(statusObj.uid == 0){
776		trace("------------------------ "+statusObj.uid)
777		trace(searchObj);
778		trace(statusObj);
779		trace(statusObj.container);
780	}
781	//output(searchObj);
782	//output(statusObj);
783	/**/
784	searchJCOMEventPresentAPI(searchObj,statusObj);
785}
786
787
788/*--------------------------------------------------------------
789	2018/10/25
790	イベントプレゼントAPI:検索
791--------------------------------------------------------------*/
792function searchJCOMEventPresentAPI(searchObj,statusObj){
793	trace("イベントプレゼントAPI:検索開始(jcom_api)");
794	
795	var message = "";
796	var url = "https://c.myjcom.jp/jsonp/event_present.js?callback=?";
797	var callback = statusObj.callback;
798	var now = new Date();
799	var nowdate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);
800	
801	jQuery.getJSON(url, searchObj, function(data, status, xhr){
802		trace("イベントプレゼントAPI:検索結果(jcom_api)");
803		var data = $.parseJSON(data);
804
805		trace(data);
806		var data_arr = [];
807		var len = data.results.length;
808		for(var i=0;i<len;i++){
809			var targetObj = data.results[i];
810
811			//  リンクのcc-対応
812			targetObj.linkurl = targetObj.link;
813			if(statusObj.addCC){
814				var link_arr = targetObj.link.split('//');
815				targetObj.link = link_arr[0]+'//cc-'+link_arr[1];
816			}
817			//trace("link "+targetObj.link);
818
819			var pubCloseDate;
820			var lastdate;
821			
822			//trace("pubCloseDate "+targetObj.pubCloseDate);
823			
824			if(targetObj.pubCloseDate){
825				//trace("pubCloseDate 有効");
826				pubCloseDate = targetObj.pubCloseDate;
827				lastdate = pubCloseDate.replace( '-', '/' );
828				while(lastdate !== pubCloseDate) {
829					pubCloseDate = pubCloseDate.replace('-', '/');
830					lastdate = lastdate.replace('-', '/');
831				}
832				targetObj.lastdate = lastdate.split(' ')[0];
833				if(targetObj.closingDateNonDisplay == "on") targetObj.pubCloseDate = '';
834
835			}else{
836				//trace("pubCloseDate 無効");
837				targetObj.pubCloseDate = "";
838			}
839
840			var pubDate = targetObj.pubDate;
841			var startdate = pubDate.replace( '-', '/' );
842			while(startdate !== pubDate) {
843					pubDate = pubDate.replace('-', '/');
844					startdate = startdate.replace('-', '/');
845			}
846			
847			//  掲載開始時期を考慮する
848			if(!statusObj.ignoreDate){
849				//trace("掲載開始時期を考慮する");
850			
851				//  掲載開始時期
852				if(pubDate != null){
853					startDay = new Date(pubDate);
854					targetObj.startDay = startDay;
855					if(startDay <= now){
856						isDisplay = true;
857					}else{
858						isDisplay = false;
859					}
860				}
861				
862				//  終了前であればリストに追加
863				if(pubCloseDate != null){
864					var endDate = new Date(lastdate);
865					targetObj.endDate = endDate;
866					if(nowdate <= endDate && isDisplay){
867						data_arr.push(targetObj);
868					}
869				}
870				
871			}else{
872				//trace("掲載開始時期を考慮しない");
873				data_arr.push(targetObj);
874			}
875
876		}//	for
877
878		/**
879		if(statusObj.uid == 0) {
880			trace("番組表API(jcom_api):検索結果 --------");
881			trace(status);	
882			trace(xhr);
883			trace(data);
884			trace(data_arr);
885		}
886		//*/
887
888		statusObj.api_type = 'event_present';
889		if(callback != null) parent[callback](data_arr,status,searchObj,statusObj);
890
891	});// jQuery.getJSON
892}
893
894/*==============================================
895	
896	2019/6/12
897	チャンネルIDのリストからチャンネル情報を返す
898	
899==============================================*/
900var loadedJcomChannelIDNum = 0;
901var loadedJcomChannelIDTotalNum = 0;
902var loadedJcomChannelIDData;
903var loadedJcomChannelIDDataCallbackFunc;
904function getJcomChannelDataByChannelIDList(list,callbackfunc){
905	loadedJcomChannelIDTotalNum = list.length;
906	loadedJcomChannelIDData = new Array(loadedJcomChannelIDTotalNum);
907	loadedJcomChannelIDDataCallbackFunc = callbackfunc;
908	
909	for(var i=0;i<loadedJcomChannelIDTotalNum;i++){
910		var searchObj = { channelId:list[i] };	
911		
912		//	制御用パラメータ
913		var statusObj = {
914				uid:i,	//	UID
915				callback:'getJcomChannelDataByChannelIDListComplete'	//	コールバック関数 デフォルト:searchProgramAPIComplete 省略可
916			};
917
918		//	データ呼び出し	jcom_api.js
919		getJcomChannelList(searchObj,statusObj);
920
921	}//	for
922}
923
924//	チャンネル情報取得コールバック
925function getJcomChannelDataByChannelIDListComplete(result,status,searchObj,statusObj){
926	//trace("チャンネル情報取得完了:getJcomChannelDataByChannelIDListComplete "+status);
927	
928	loadedJcomChannelIDNum ++;
929	loadedJcomChannelIDData[statusObj.uid] = result.channel[0];
930	
931	//trace(loadedJcomChannelNum +" / "+loadedJcomChannelTotalNum +"  "+statusObj.uid);
932	
933	if(loadedJcomChannelIDTotalNum <= loadedJcomChannelIDNum ){
934		if(loadedJcomChannelIDDataCallbackFunc != null) parent[loadedJcomChannelIDDataCallbackFunc](loadedJcomChannelIDData,status,searchObj,statusObj);
935	}
936}
937
938/*==============================================
939	
940	2018/5/23
941	チャンネル名のリストからチャンネル情報を返す
942	
943==============================================*/
944var loadedJcomChannelNum = 0;
945var loadedJcomChannelTotalNum = 0;
946var loadedJcomChannelData;
947var loadedJcomChannelDataCallbackFunc;
948var loadedJcomChanneIsNodataList = [];
949function getJcomChannelDataByChannelList(list,callbackfunc){
950	loadedJcomChannelTotalNum = list.length;
951	loadedJcomChannelData = new Array(loadedJcomChannelTotalNum);
952	loadedJcomChannelDataCallbackFunc = callbackfunc;
953
954	for(var i=0;i<loadedJcomChannelTotalNum;i++){
955		var channel = list[i];		
956		var data = getChannelDataByName(channel);//	チャンネル名からチャンネル情報を取得
957		//trace(i+" チャンネル名のリストからチャンネル情報を返す "+channel);
958		//trace(data.channelID);
959		
960		var searchObj = { channelId:data.channelID };	
961		
962		//if(channel == 'スポーツライブ+') searchObj = { channelId:'410' };	
963
964		//	制御用パラメータ
965		var statusObj = {
966				uid:i,	//	UID
967				callback:'getJcomChannelDataByChannelListOneDataLoadedComplete'	//	コールバック関数 デフォルト:searchProgramAPIComplete 省略可
968			};
969
970		//	データ呼び出し	jcom_api.js
971		getJcomChannelList(searchObj,statusObj);
972
973	}//	for
974}
975
976//	チャンネル情報取得コールバック
977function getJcomChannelDataByChannelListOneDataLoadedComplete(result,status,searchObj,statusObj){
978//	trace("チャンネル情報取得完了:getJcomChannelDataByChannelListOneDataLoadedComplete "+status+":"+searchObj.channelId);
979//	trace(loadedJcomChannelData);
980//	trace(result);
981//	trace("result.channel.length  "+result.channel.length );
982//	
983
984	loadedJcomChannelNum ++;
985	loadedJcomChannelData[statusObj.uid] = result.channel[0];	
986	
987	if(Object.prototype.toString.call(result.channel[0]) !== "[object Object]"){
988		//trace("objectではない "+statusObj.uid);
989		loadedJcomChanneIsNodataList.push(statusObj.uid);
990	}
991	
992	if(loadedJcomChannelTotalNum <= loadedJcomChannelNum ){
993//		trace("全てのチャンネル情報取得完了:getJcomChannelDataByChannelListOneDataLoadedComplete "+status);
994//		trace(loadedJcomChannelData);
995		
996		var resultList = [];
997		var len = loadedJcomChannelData.length;
998		for(var i=0;i<len;i++){
999			var data = loadedJcomChannelData[i];
1000			
1001			var isNG = false;
1002			var len2 = loadedJcomChanneIsNodataList.length;
1003			for(var v=0;v<len2;v++){
1004				var id = loadedJcomChanneIsNodataList[v];
1005				if(id == i) isNG = true;
1006			}//	for
1007			
1008			if(!isNG) resultList.push(data);
1009			
1010		}//	for
1011		
1012		if(loadedJcomChannelDataCallbackFunc != null) parent[loadedJcomChannelDataCallbackFunc](resultList);
1013		
1014		//if(loadedJcomChannelDataCallbackFunc != null) parent[loadedJcomChannelDataCallbackFunc](loadedJcomChannelData);
1015	}
1016}
1017
1018
1019/*==============================================
1020	
1021	2019/6/14
1022	チャンネル名のリストからチャンネル情報を返す(まとめて取得)
1023	
1024==============================================*/
1025var jcomChannelDataByChannelList;
1026var jcomChannelDataByChannelIDList = [];
1027var jcomChannelDataByChannelListCallbackFunc;
1028function getJcomChannelAllDataByChannelList(list,callbackfunc,targetChannels){
1029	jcomChannelDataByChannelList = list;
1030	jcomChannelDataByChannelListCallbackFunc = callbackfunc;
1031
1032	var len = jcomChannelDataByChannelList.length;
1033	for(var i=0;i<len;i++){
1034		var data = getChannelDataByName(jcomChannelDataByChannelList[i]);
1035		///trace(data);
1036		var channelID = data.channelID;
1037		jcomChannelDataByChannelIDList.push(channelID);
1038	}//	for
1039	
1040	//	APIパラメータ
1041	var searchObj = {
1042		targetChannels:targetChannels,	//	放送波種別 0(CATV)、1(コミュニティチャンネル)、2(BS)、3(地デジ)、4(FM放送) カンマ区切りで複数設定可
1043	};	
1044	
1045	//	制御用パラメータ
1046	var statusObj = {
1047			uid:0,	//	UID
1048		callback:'getJcomChannelAllDataByChannelListComplete'	//	コールバック関数 デフォルト:searchProgramAPIComplete 省略可
1049	};
1050	//	データ呼び出し	jcom_api.js
1051	getJcomChannelList(searchObj,statusObj);
1052}
1053
1054function getJcomChannelAllDataByChannelListComplete(result,status,searchObj,statusObj){
1055	trace('getJcomChannelAllDataByChannelListComplete jcom_api.js')
1056	trace(result);
1057	
1058	var resultList = [];
1059	var channelList = result.channel;
1060	var datalen = jcomChannelDataByChannelList.length;
1061	var channellen = channelList.length;
1062
1063	for(var i=0;i<datalen;i++){
1064		var channelID = jcomChannelDataByChannelIDList[i];
1065		for(var v=0;v<channellen;v++){
1066			var id = channelList[v].channelId;
1067			if(channelID == id){
1068				resultList.push(channelList[v]);
1069				break;
1070			}
1071		}//	for
1072	}//	for
1073	
1074	if(jcomChannelDataByChannelListCallbackFunc != null) parent[jcomChannelDataByChannelListCallbackFunc](resultList);
1075}
1076
1077/*==============================================
1078	
1079	2018/4/26
1080	チャンネル情報API
1081
1082	//	APIパラメータ
1083	var searchObj = {
1084		//areaId:12,	// エリアID 省略可
1085		//course:1,	// コースID デフォルト(指定なし)、1(スタンダードプラス)、2(スタンダード)、3(コンパクト)、4(セレクトA)、5(セレクトB)、6(セレクトC)
1086		//channelId:'159_65406',	//	チャンネルID カンマ区切りで複数設定可(OR検索)
1087		//option:'159_65406',	//	オプションフラグ カンマ区切りで複数設定可(OR検索)
1088		genre:'2001',	//	ジャンルID デフォルト(指定なし)で全てのジャンル カンマ区切りで複数設定可(OR検索)
1089		//subGenre:'3001,3003',	// サブジャンルID カンマ区切りで複数指定可(OR検索)。未指定時は全サブジャンル指定となる。
1090		//targetChannels:'0,1',",	//	放送波種別 0(CATV)、1(コミュニティチャンネル)、2(BS)、3(地デジ)、4(FM放送) カンマ区切りで複数設定可
1091		//sort:0,	//	ソート種別 0(放送日時:デフォルト)、1(チャンネル)、2(ジャンルID)
1092		//order:0,	//	昇降順 0(昇順:デフォルト)、1(降順)
1093		//getFeatureInfo:1,//注目情報要求フラグ 1でリクエストされた場合、注目番組情報をレスポンスに含める。
1094	};	
1095	
1096	//	制御用パラメータ
1097	var statusObj = {
1098		uid:0,	//	UID
1099		container:'.tv_channel_list',		//	番組表格納コンテナ(.付きの文字列で指定)デフォルト:.tv_program_list 省略可
1100		callback:'searchChannelAPIComplete'	//	コールバック関数 デフォルト:searchProgramAPIComplete 省略可
1101	};
1102	
1103	//	データ呼び出し	jcom_api.js
1104	getJcomChannelList(searchObj,statusObj);
1105	
1106==============================================*/
1107function getJcomChannelList(_searchObj,_statusObj){
1108	//trace("チャンネル情報API(jcom_api.j):getJcomChannelList");
1109	setCurrentTimeForAPI();
1110	var searchObj = {};
1111	var statusObj = {};
1112	
1113	// _searchObjからAPI検索用Objを抽出
1114	
1115	if(!_searchObj.areaId != null){
1116		var aid = jQuery.cookie("area_id");
1117		
1118		if(aid != undefined){
1119			area_id = aid;
1120		}else{
1121			area_id = 12;
1122		}
1123		searchObj.areaId = area_id;
1124	}
1125
1126	if(_searchObj.getFeatureInfo != null){
1127		searchObj.getFeatureInfo = _searchObj.getFeatureInfo;
1128	}
1129	
1130	if(_searchObj.course != null){
1131		searchObj.course = _searchObj.course;
1132	}
1133	if(_searchObj.channelId != null){
1134		searchObj.channelId = _searchObj.channelId;
1135	}
1136	if(_searchObj.option != null){
1137		searchObj.option = _searchObj.option;
1138	}
1139	if(_searchObj.genre != null){
1140		searchObj.genre = _searchObj.genre;
1141	}
1142	/**/
1143	//	サブジャンルは有効ではない? 2018/4/27
1144//	if(_searchObj.subGenre != null){
1145//		searchObj.subGenre = _searchObj.subGenre;
1146//	}//*/
1147	if(_searchObj.course != null){
1148		searchObj.course = _searchObj.course;
1149	}
1150	if(_searchObj.targetChannels != null){
1151		searchObj.targetChannels = _searchObj.targetChannels;
1152	}
1153	if(_searchObj.sort != null){
1154		searchObj.sort = _searchObj.sort;
1155	}
1156	if(_searchObj.order != null){
1157		searchObj.order = _searchObj.order;
1158	}
1159	
1160	
1161	// _statusObjから制御用Objを抽出
1162	
1163	if(_statusObj.uid != null) statusObj.uid = _statusObj.uid;
1164	
1165	if(_statusObj.container != null){
1166		statusObj.container = _statusObj.container;
1167	}else{
1168		statusObj.container = '.tv_channel_list';
1169	}
1170
1171	if(_statusObj.callback != null){
1172		statusObj.callback = _statusObj.callback;
1173	}else{
1174		statusObj.callback = "searchChannelAPIComplete";
1175	}
1176	if(_statusObj.research != null){
1177		statusObj.research = _statusObj.research;
1178	}else{
1179		statusObj.research = false;
1180	}
1181
1182	// コールバックパラメータ名の指定
1183	jsonpCallbackUID ++;
1184	statusObj.jsonpCallback = 'search_channel'+jsonpCallbackUID;
1185
1186	/**
1187	trace("------------------------ チャンネルAPI(jcom_api) "+statusObj.uid)
1188	trace(searchObj);
1189	trace(statusObj);
1190	trace(statusObj.container);
1191	//output(searchObj);
1192	//output(statusObj);
1193	/**/
1194	searchJCOMChannelAPI(searchObj,statusObj);
1195}
1196
1197/*--------------------------------------------------------------
1198	チャンネルAPI:検索
1199--------------------------------------------------------------*/
1200function searchJCOMChannelAPI(searchObj,statusObj){
1201  //trace("チャンネルAPI(jcom_api.js):検索");
1202	var result = [];
1203	var message = "";
1204	var dataType = "jsonp";
1205	var jsonpCallback = statusObj.jsonpCallback;
1206	var url = 'https://tvguide.myjcom.jp/api/getChannelInfo/?';
1207	//if(isStage) url = "https://stage-tvguide.myjcom.jp/api/getChannelInfo/?";
1208
1209	if(isMyjcom){
1210		url += "callback=?"+getAPIRequestQuery(searchObj,false);
1211		//trace("チャンネルAPI:myjcom "+url);
1212	}else{
1213		var param = getAPIRequestQuery(searchObj,true);
1214		//url = api_php_path+url+param;
1215		url = api_php_path+'wrp='+jsonpCallback+'&url='+url+param;
1216		url = location.protocol+"//"+location.host+url;	// ローカルからアクセスできるよう絶対パスで指定
1217		//trace("チャンネルAPI:other "+url);
1218	}
1219
1220	var callback = statusObj.callback;
1221	var load_status;
1222
1223	$.ajax({
1224		url: url,
1225		type:'POST',
1226		dataType: dataType,
1227		jsonpCallback: jsonpCallback // コールバックパラメータ名の指定
1228	}).done(function(data){ // Ajaxリクエストが成功した時発動
1229		//trace("チャンネルAPI(jcom_api.js):検索 DONE");
1230		//trace(data);
1231		load_status = 0;
1232		result = data;
1233		}).fail(function(data){  // Ajaxリクエストが失敗した時発動
1234		//trace("チャンネルAPI(jcom_api.js):検索 FAIL");
1235		//trace(data);
1236		result = ["APIエラー:"+data.errorMassage];
1237		message = ["APIエラー:"+data.errorMassage];
1238		load_status = 2;
1239	}).always(function(data){  // Ajaxリクエストが成功・失敗どちらでも発動
1240		//trace("チャンネルAPI(jcom_api.js):検索 FAIL");
1241
1242		statusObj.api_type = 'channel';
1243		if(callback != null) parent[callback](result,load_status,searchObj,statusObj);
1244	});//$.ajax({
1245
1246}
1247
1248
1249
1250/*==============================================
1251	
1252	2018/4/26
1253	おすすめAPI
1254
1255	//	APIパラメータ
1256	var searchObj = {
1257		//kijiId:0000077684,	// おすすめ記事ID 記事IDが指定された場合には、記事ID以外のリクエストパラメータは全て無視し、記事IDでのみ検索を行う。
1258		//serviceCode:'191_4,570_65406',	// サービスコード チャンネルを指定する。serviceId+'_'+networkIdで構成。カンマ区切りで複数指定可(OR検索)。
1259		//genre:'2001,2003',	// ジャンルID カンマ区切りで複数指定可(OR検索)。未指定時は全ジャンル指定となる。
1260		//subGenre:'3001,3003',	// サブジャンルID カンマ区切りで複数指定可(OR検索)。未指定時は全サブジャンル指定となる。
1261		since:'201804271200',	// 放送日(開始)yyyyMMddHHmmで指定する。時間指定は0000~2359の間で可能。
1262		until:'201805071200',	// 放送日(終了)yyyyMMddHHmmで指定する。時間指定は0000~2359の間で可能。
1263		//main:0,	// メインフラグ 0(イチオシなし:デフォルト)、1(メインジャンルのイチオシ、およびサブジャンルを内包するメインジャンルのイチオシ)、2(サブジャンルのイチオシ)
1264		//sort:0,	// ソート種別 0(放送日時:デフォルト)、1(チャンネル)、2(ジャンルID)
1265		//order:0,	// 昇降順 0(昇順:デフォルト)、1(降順)
1266		//offset:0,	// オフセット 返却する候補の最初の件数を指定する。Offsetで指定された番目からlimit件検索結果を返却する。
1267		limit:10,	// 最大取得件数 1~100件まで指定可。
1268	};	
1269		
1270	//	制御用パラメータ
1271	var statusObj = {
1272		uid:0,	//	UID
1273		container:'.tv_program_list',		//番組表格納コンテナ(.付きの文字列で指定)デフォルト:.tv_program_list 省略可
1274		ng_perfectmatching:false,	//	NGワードを完全一致とする(true)しない(false:デフォルト) 省略可
1275		ngwords:['スター・ウォーズ','科学'],	//	NGワード 配列で複数設定可能 省略可
1276		//unuseNgWords:true,	//	NGワードをキャンセル(true)する、しない(false:デフォルト) 省略可
1277		//research:false,	//	タグなどでの再検索の場合(true)通常検索の場合(false:デフォルト) 省略可
1278		callback:'searchRecommendProgramAPIComplete'	//	コールバック関数 デフォルト:searchProgramAPIComplete 省略可
1279	};	
1280		
1281		
1282	//	データ呼び出し	jcom_api.js
1283	getJcomRecommendProgram(searchObj,statusObj);
1284	
1285==============================================*/
1286function getJcomRecommendProgram(_searchObj,_statusObj){
1287	trace("おすすめAPI:jcom_api.js getJcomRecommendProgram");
1288	setCurrentTimeForAPI();
1289	
1290	var searchObj = {};
1291	var statusObj = {};
1292	
1293	// _searchObjからAPI検索用Objを抽出
1294	
1295	if(!_searchObj.areaId != null){
1296		var aid = jQuery.cookie("area_id");
1297		if(aid != undefined){
1298			area_id = aid;
1299		}else{
1300			area_id = 12;
1301		}
1302		searchObj.areaId = area_id;
1303	}
1304	
1305	if(_searchObj.kijiId != null){
1306		searchObj.kijiId = _searchObj.kijiId;
1307	}
1308	if(_searchObj.serviceCode != null){
1309		searchObj.serviceCode = _searchObj.serviceCode;
1310	}
1311	if(_searchObj.genre != null){
1312		searchObj.genre = _searchObj.genre;
1313	}
1314	if(_searchObj.subGenre != null){
1315		searchObj.subGenre = _searchObj.subGenre;
1316	}
1317	if(_searchObj.since != null){
1318		searchObj.since = _searchObj.since;
1319	}
1320	if(_searchObj.until != null){
1321		searchObj.until = _searchObj.until;
1322	}
1323	if(_searchObj.main != null){
1324		searchObj.main = _searchObj.main;
1325	}
1326	if(_searchObj.sort != null){
1327		searchObj.sort = _searchObj.sort;
1328	}
1329	if(_searchObj.order != null){
1330		searchObj.order = _searchObj.order;
1331	}
1332	if(_searchObj.offset != null){
1333		searchObj.offset = _searchObj.offset;
1334	}
1335
1336	if(_searchObj.limit != null){
1337		searchObj.limit = 100;
1338		statusObj.limit = _searchObj.limit;
1339	}else{
1340		searchObj.limit = 100;
1341		statusObj.limit = 10;
1342	}
1343	// _statusObjから制御用Objを抽出
1344	
1345	if(_statusObj.uid != null) statusObj.uid = _statusObj.uid;
1346	if(_statusObj.container != null){
1347		statusObj.container = _statusObj.container;
1348	}else{
1349		statusObj.container = '.recommend_program_list';
1350	}
1351	if(_statusObj.container_parent != null){
1352		statusObj.container_parent = _statusObj.container_parent;
1353	}
1354	if(_statusObj.callback != null){
1355		statusObj.callback = _statusObj.callback;
1356	}else{
1357		statusObj.callback = "searchProgramAPIComplete";
1358	}
1359	if(_statusObj.research != null){
1360		statusObj.research = _statusObj.research;
1361	}else{
1362		statusObj.research = false;
1363	}
1364	
1365	if(_statusObj.only_pickup != null){
1366		statusObj.only_pickup = _statusObj.only_pickup;
1367	}else{
1368		statusObj.only_pickup = false;
1369	}
1370
1371	// コールバックパラメータ名の指定
1372	jsonpCallbackUID ++;
1373	statusObj.jsonpCallback = 'search_recommend'+jsonpCallbackUID;
1374
1375	/**/
1376	trace("------------------------ おすすめ番組 "+statusObj.uid)
1377	trace(searchObj);
1378	trace(statusObj);
1379	trace(statusObj.container);
1380	//output(searchObj);
1381	//output(statusObj);
1382	/**/
1383	searchJCOMRecommendProgramAPI(searchObj,statusObj);
1384}
1385
1386/*--------------------------------------------------------------
1387	2019/3/22
1388	おすすめAPI:検索
1389--------------------------------------------------------------*/
1390function searchJCOMRecommendProgramAPI(searchObj,statusObj){
1391	trace("おすすめAPI:検索(jcom_api)");
1392
1393	var result = [];
1394	var message = "";
1395	var dataType = "jsonp";
1396	var jsonpCallback = statusObj.jsonpCallback;
1397	var url = 'https://tvguide.myjcom.jp/api/getRecommendProgramInfo/?';
1398	//if(isStage) url = "https://stage-tvguide.myjcom.jp/api/getRecommendProgramInfo/?";
1399
1400	if(isMyjcom){
1401		url += "callback=?"+getAPIRequestQuery(searchObj,false);
1402		trace("おすすめAPI:myjcom "+url);
1403	}else{
1404		var param = getAPIRequestQuery(searchObj,true);
1405		//url = api_php_path+url+param;
1406		url = api_php_path+'wrp='+jsonpCallback+'&url='+url+param;
1407		url = location.protocol+"//"+location.host+url;	// ローカルからアクセスできるよう絶対パスで指定
1408		trace("おすすめAPI:other "+url);
1409	}
1410	var callback = statusObj.callback;
1411	var load_status;
1412	/**/
1413	$.ajax({
1414		url: url,
1415		type:'POST',
1416			dataType: dataType,
1417		jsonpCallback: jsonpCallback // コールバックパラメータ名の指定
1418	}).done(function(data){ // Ajaxリクエストが成功した時発動
1419		trace("おすすめAPI:検索 DONE(jcom_api)");
1420		trace(data);
1421		load_status = 0;
1422		result = [];
1423
1424		jQuery.each(data.contents, function(key, obj){
1425			// trace(key);
1426			// trace(obj);
1427
1428			var dateObj = new Date(obj.startDate);
1429			var month = formatDate(dateObj, 'MM');
1430			var day = formatDate(dateObj, 'DD');
1431			var week = formatDate(dateObj, 'W');
1432
1433			obj.datestr = month+'月'+day+'日('+week+')';
1434			obj.datestr_single = Number(month)+'月'+Number(day)+'日('+week+')';
1435			obj.datestr_simple = month+'/'+day+'('+week+')';
1436			obj.datestr_simple_single = Number(month)+'/'+Number(day)+'('+week+')';
1437			obj.datestr_simple_single2 = Number(month)+'/'+Number(day)+'('+week+')';
1438
1439			if(obj.photo.length != 0){
1440				obj.thumbnail = obj.photo[0].photo;
1441				obj.copyright = obj.photo[0].copyright;
1442				obj.hasImage = true;
1443			}else{
1444				obj.thumbnail = '/special/common/images/no_image_800x448.jpg';
1445				obj.hasImage = false;
1446			}
1447
1448			if(obj.channel.length != 0){
1449				obj.channelLogoUrl = obj.channel[0].channelLogoUrl;
1450				obj.channelName = obj.channel[0].channelName;
1451				obj.channelType = obj.channel[0].channelType;
1452				obj.channelId = obj.channel[0].channelId;
1453				obj.channelUrl = obj.channel[0].channelUrl;
1454				obj.digitalNo = obj.channel[0].digitalNo;
1455			}else{
1456
1457			}
1458
1459			result.push(obj);
1460
1461		});//jQuery.each
1462
1463	}).fail(function(data){  // Ajaxリクエストが失敗した時発動
1464		trace("おすすめAPI:検索 FAIL(jcom_api)");
1465		trace(data);
1466		////trace("APIエラー:"+data.errorMassage);
1467		result = ["APIエラー:"+data.errorMassage];
1468		message = ["APIエラー:"+data.errorMassage];
1469		load_status = 2;
1470
1471	}).always(function(data){  // Ajaxリクエストが成功・失敗どちらでも発動
1472		trace("おすすめAPI:検索 ALWAYS(jcom_api)");
1473
1474		statusObj.api_type = 'recommend';
1475
1476
1477		if(callback != null) parent[callback](result,load_status,searchObj,statusObj);
1478	});//$.ajax({
1479
1480  //*/
1481
1482}
1483
1484/*==============================================
1485	
1486	2019/6/21
1487	番組表API
1488
1489	//	APIパラメータ
1490	var searchObj = {
1491			//areaId:12,	// エリアID 省略可
1492		//genreId:6,	// ジャンルID
1493		course:4,	// コースID デフォルト(指定なし)、1(スタンダードプラス)、2(スタンダード)、3(コンパクト)、4(セレクトA)、5(セレクトB)、6(セレクトC)
1494		keyword:'宇宙',	//	検索ワード APIではqueryで処理
1495		limit:10,	//	検索結果数
1496		//targetChannels:'0,1',		//	検索対象の放送波 0(CATV)、1(コミュチャン)、2(BS)、3(地デジ)カンマ区切りで複数設定可
1497		//serviceCode:'561_65406,560_65406',	
1498		queryTarget:0,	//	検索対象 0(すべて:初期設定)、1(番組名)、2(番組内容) 省略可
1499		queryType:0,	//	0(and検索), 1(or検索)
1500		since:'201906210000',//	放送日(開始)
1501		until:'201906210000',//	放送日(終了)
1502		title:null,	//	検索時のタイトル、省略時はキーワードなどが適宜入る
1503		freeCaMode:null, // CAモード	 デフォルトなし
1504		attr:null, // イベント属性 デフォルトなし
1505		image:0,	// 画像の有無 0(全て),1(画像ありのみ)
1506		hasTag:0,	// 関連番組タグキーワード有無 0(全て),1(タグありのみ)
1507		recommend:0,	// おすすめ番組フラグ 0(全て),1(おすすめフラグ有りのみ)
1508		getImage:0,	// 画像取得 0(しない),1(する)
1509		excludeTitle:'放送休止,インフォメーション', // 除外タイトル 番組タイトル部分一致で検索結果から除外するキーワードを指定する。カンマ区切りでor条件による複数指定可能。
1510		excludeServiceCode:'033_65406,034_65406', // 除外サービスコード 検索結果から除外するサービスコードを指定する。カンマ区切りで複数指定可能。
1511		excludeAttr:'4k,han,hua', // 除外イベント属性 検索結果から除外するイベント属性を指定する。カンマ区切りで複数指定可能。
1512		alignment:'new,feature,classic', // 番組マスタまとめフラグ 番組マスタ管理画面から登録した任意文字列のフラグを指定する。カンマ区切りで複数指定可能。
1513		alignment_title:'BTS特集と年末年始一挙放送と年末年始特番',// フラグ名を表示する際の文言、設定ない場合はフラグそのまま。
1514
1515	};	
1516	
1517	//	制御用パラメータ
1518	var statusObj = {
1519		uid:0,	//	UID
1520		container:'.tv_program_list',		//番組表格納コンテナ(.付きの文字列で指定)デフォルト:.tv_program_list 省略可
1521		//container_parent:'.section_relation_program',	// [Bランクでは設定NG!] 検索結果がない場合やエラー発生時、非表示にするエリア(.付きの文字列で指定)デフォルト:.section_relation_program .content_program(Bランク用)
1522		ng_perfectmatching:false,	//	NGワードを完全一致とする(true)しない(false:デフォルト) 省略可
1523		ngwords:['スター・ウォーズ','科学'],	//	NGワード 配列で複数設定可能 省略可
1524		unuseNgWords:true,	//	NGワードをキャンセル(true)する、しない(false:デフォルト) 省略可
1525		research:false,	//	タグなどでの再検索の場合(true)通常検索の場合(false:デフォルト) 省略可
1526		nodata_hide:true,	//	検索結果がない場合やエラー発生時、エリアごと非表示にする(true:デフォルト)しない(false) 省略可
1527		displayN:10,	//	もっと見るボタンを表示。指定数ずつ番組を表示する 省略可
1528		callback:'searchProgramAPIComplete',	//	コールバック関数 デフォルト:searchProgramAPIComplete 省略可
1529		useRecommend:0,// おすすめ番組フラグを利用 0(しない:デフォルト),1(する)
1530	};	
1531		
1532	//	データ呼び出し
1533	getJcomProgramList(searchObj,statusObj);
1534	
1535==============================================*/
1536
1537var defaultNGwords = ['番組案内','番組ガイド','メガパックで配信中!'];
1538function getJcomProgramList(_searchObj,_statusObj){
1539	setCurrentTimeForAPI();
1540	var user_area_id = jQuery.cookie("area_id");
1541	if(user_area_id == undefined){
1542		user_area_id = 12;
1543	}
1544	var searchObj = {};
1545	var statusObj = {};
1546	
1547
1548	//	2022/7/1追加
1549	if(_searchObj.course != null){
1550		searchObj.course =  _searchObj.course;
1551	}
1552	
1553	//	2021/3/29追加
1554	if(_searchObj.excludeTitle != null){
1555		searchObj.excludeTitle =  _searchObj.excludeTitle;
1556	}
1557	if(_searchObj.excludeServiceCode != null){
1558		searchObj.excludeServiceCode =  _searchObj.excludeServiceCode;
1559	}
1560	if(_searchObj.excludeAttr != null){
1561		searchObj.excludeAttr =  _searchObj.excludeAttr;
1562	}
1563	
1564	
1565	
1566	/* 番組マスタまとめフラグ */
1567	if(_searchObj.alignment != null){
1568		searchObj.alignment =  _searchObj.alignment;
1569	}
1570	if(_searchObj.alignment_title != null){
1571		searchObj.alignment_title =  _searchObj.alignment_title;
1572	}else{
1573		searchObj.alignment_title =  _searchObj.alignment;
1574	}
1575	
1576	//	2020/2/21追加
1577	if(_searchObj.freeCaMode != null){
1578		searchObj.freeCaMode =  _searchObj.freeCaMode;
1579	}
1580	if(_searchObj.attr != null){
1581		searchObj.attr =  _searchObj.attr;
1582	}
1583	if(_searchObj.image != null){
1584		searchObj.image =  _searchObj.image;
1585	}else{
1586		searchObj.image = 0;
1587	}
1588	if(_searchObj.hasTag != null){
1589		searchObj.hasTag =  _searchObj.hasTag;
1590	}
1591	if(_searchObj.recommend != null){
1592		searchObj.recommend =  _searchObj.recommend;
1593	}else{
1594		searchObj.recommend = 0;
1595	}
1596	if(_searchObj.getImage != null){
1597		searchObj.getImage = _searchObj.getImage;
1598		//if(_searchObj.getImage == 1) searchObj.image = 1;
1599	}else{
1600		searchObj.getImage = 1;//
1601	}
1602	
1603	if(_searchObj.adult != null){
1604		searchObj.adult =  _searchObj.adult;
1605	}else{
1606		searchObj.adult = 0;
1607	}
1608	if(_searchObj.since != null){
1609		searchObj.since =  _searchObj.since;
1610	}
1611	if(_searchObj.until != null){
1612		searchObj.until =  _searchObj.until;
1613	}
1614
1615	if(_searchObj.attr != null){
1616		searchObj.attr =  _searchObj.attr;
1617	}
1618
1619	if(_searchObj.areaId != null){
1620		searchObj.areaId =  _searchObj.areaId;
1621	}else{
1622		searchObj.areaId = user_area_id;
1623	}
1624
1625	if(_searchObj.limit != null){
1626		searchObj.limit = Number(_searchObj.limit);
1627	}else{
1628		searchObj.limit = 100;
1629	}
1630
1631
1632	if(_searchObj.keyword != null){
1633    searchObj.query = _searchObj.keyword;
1634    searchObj.keyword = _searchObj.keyword;
1635	}
1636	
1637	if(_searchObj.genreId != null){
1638		if(_searchObj.genreId != 'null'){
1639			searchObj.genreId = encodeURI(_searchObj.genreId);
1640			if(searchObj.keyword == ""){
1641				searchObj.keyword = getProgramAPIGenrIDName(searchObj.genreId);
1642				//trace(searchObj.genreId+"  searchObj.keyword "+searchObj.keyword);
1643			};
1644		}
1645	}
1646	
1647	//	放送波の設定あればチャンネル設定無効
1648	if(_searchObj.targetChannels != null){
1649		//trace("_searchObj.targetChannels ある "+_searchObj.targetChannels);
1650		searchObj.targetChannels = _searchObj.targetChannels;
1651		
1652		var targetChannels_arr = _searchObj.targetChannels.split(',');
1653		var wavename = "";
1654		if(1 < targetChannels_arr.length){
1655			
1656			for(var i=0;i<targetChannels_arr.length;i++){			
1657				if(i < 4){
1658					if(i != 0) wavename += " / ";
1659					wavename += getTargetChannelTypeByID(targetChannels_arr[i]);	
1660				}
1661			}//	for				
1662		}else{
1663			wavename = getTargetChannelTypeByID(_searchObj.targetChannels);
1664		}
1665		if(searchObj.keyword == "") searchObj.keyword = wavename;
1666	
1667	}else{
1668		if(_searchObj.serviceCode != null){
1669			trace("_searchObj.serviceCode ある "+_searchObj.serviceCode);
1670			
1671			searchObj.serviceCode = _searchObj.serviceCode;
1672			var serviceCode_arr = _searchObj.serviceCode.split(',');
1673			var chname = "";
1674			if(1 < serviceCode_arr.length){
1675				
1676				for(var i=0;i<serviceCode_arr.length;i++){			
1677					if(i < 3){
1678						if(i != 0) chname += " / ";
1679						chname += getChannelNameByServiceCode(serviceCode_arr[i]);					
1680					}else if(i == 3){
1681						chname += " などのチャンネル";
1682					}
1683				}//	for				
1684			}else{
1685				chname = getChannelNameByServiceCode(_searchObj.serviceCode);
1686			}
1687			
1688			if(searchObj.keyword == "") searchObj.keyword = chname;
1689		}
1690	}
1691	
1692	if(_searchObj.queryType != null){
1693		searchObj.queryType = Number(_searchObj.queryType);
1694	}else{
1695		searchObj.queryType = 0;
1696	}
1697	
1698	if(_searchObj.queryTarget != null){
1699		searchObj.queryTarget = _searchObj.queryTarget;
1700	}else{
1701		searchObj.queryTarget = 0;
1702	}
1703	
1704	// _statusObjから制御用Objを抽出
1705	
1706	if(_statusObj.uid != null) statusObj.uid = _statusObj.uid;
1707	if(_statusObj.container != null){
1708		statusObj.container = _statusObj.container;
1709	}else{
1710		statusObj.container = '.tv_program_list';
1711	}
1712	if(_statusObj.container_parent != null){
1713		statusObj.container_parent = _statusObj.container_parent;
1714	}else{
1715		statusObj.container_parent = '.section_relation_program .content_program';
1716	}
1717	
1718	if(_statusObj.ng_perfectmatching != null){
1719		statusObj.ng_perfectmatching = _statusObj.ng_perfectmatching;
1720	}else{
1721		statusObj.ng_perfectmatching = false;
1722	}
1723	if(_statusObj.ngwords != null){
1724		if(isArray(_statusObj.ngwords)){
1725			statusObj.ngwords = _statusObj.ngwords.concat(defaultNGwords);
1726		}else{
1727			statusObj.ngwords = _statusObj.ngwords.split(',').concat(defaultNGwords);
1728		}
1729	}else{
1730		statusObj.ngwords = defaultNGwords;
1731	}
1732	if(_statusObj.unuseNgWords != null){
1733		if(_statusObj.unuseNgWords) statusObj.ngwords = [];
1734	}
1735	if(_statusObj.callback != null){
1736		statusObj.callback = _statusObj.callback;
1737	}else{
1738		statusObj.callback = "searchProgramAPIComplete";
1739	}
1740	if(_statusObj.research != null){
1741		statusObj.research = _statusObj.research;
1742	}else{
1743		statusObj.research = false;
1744	}
1745	if(_statusObj.nodata_hide != null){
1746		statusObj.nodata_hide = _statusObj.nodata_hide;
1747	}else{
1748		statusObj.nodata_hide = true;
1749	}
1750	
1751	if(_searchObj.title != null){
1752		searchObj.keyword = _searchObj.title;
1753	}
1754	
1755	if(searchObj.keyword == "") searchObj.keyword = "検索条件なし";
1756	
1757	if(_searchObj.since != null){
1758		searchObj.since = _searchObj.since;
1759	}
1760	if(_searchObj.until != null){
1761		searchObj.until = _searchObj.until;
1762	}
1763	
1764	//	もっと見るボタンでの表示数
1765	if(_statusObj.displayN != null){
1766		statusObj.displayN = _statusObj.displayN;
1767	}
1768	
1769	//	もっと見るボタンでの表示数
1770	if(_statusObj.useRecommend != null){
1771		statusObj.useRecommend = _statusObj.useRecommend;
1772	}else{
1773		statusObj.useRecommend = 0;
1774	}
1775	
1776	// コールバックパラメータ名の指定
1777	jsonpCallbackUID ++;
1778	statusObj.jsonpCallback = 'search_program'+jsonpCallbackUID;
1779
1780	/**/
1781	if(statusObj.uid == 0){
1782		trace("------------------------ 番組表 "+statusObj.uid)
1783		trace(searchObj);
1784		trace(statusObj);
1785		trace(statusObj.container);
1786	}
1787	//output(searchObj);
1788	//output(statusObj);
1789	/**/
1790	searchJCOMProgramAPI(searchObj,statusObj);
1791}
1792
1793function isArray(obj) {
1794    return Object.prototype.toString.call(obj) === '[object Array]';
1795}
1796/*--------------------------------------------------------------
1797	番組表API:検索
1798--------------------------------------------------------------*/
1799function searchJCOMProgramAPI(searchObj,statusObj){
1800	//trace('番組表API(jcom_api):検索');
1801	var result = [];
1802	var message = "";
1803	var dataType = "jsonp";
1804	var jsonpCallback = statusObj.jsonpCallback;
1805	var url = "https://tvguide.myjcom.jp/api/getProgramInfo/?";
1806	var getImage = searchObj.getImage;
1807
1808	// trace(searchObj);
1809	// trace(statusObj);
1810
1811	if(isMyjcom){
1812		url += "callback=?"+getAPIRequestQuery(searchObj,false);
1813		//trace("番組表API(jcom_api):myjcom "+url);
1814	}else{
1815		var param = getAPIRequestQuery(searchObj,true);
1816		url = api_php_path+'wrp='+jsonpCallback+'&url='+url+param;
1817		url = location.protocol+"//"+location.host+url;	// ローカルからアクセスできるよう絶対パスで指定
1818		//trace("番組表API(jcom_api):other "+url);
1819	}
1820
1821	var callback = statusObj.callback;
1822	var load_status;
1823
1824	$.ajax({
1825		url: url,
1826		type:'POST',
1827		dataType: dataType,
1828		jsonpCallback: jsonpCallback
1829	}).done(function(data){ // Ajaxリクエストが成功した時発動
1830		//trace("番組表API(jcom_api):DONE");
1831		//trace(data);
1832
1833		if(data === undefined) {
1834			result = ['検索失敗(data === undefined)'];    
1835			load_status = 2;
1836			trace("検索失敗(番組表API(jcom_api):DONE)");
1837			return;
1838		}
1839		/**/
1840		// trace("======================");
1841		// trace(data);
1842		//*/
1843		load_status = data.status;
1844		if(load_status != 0) return;
1845		var pdata = data.programs;
1846		//trace(pdata);
1847
1848		//	トータル番組数
1849		statusObj.totalCount = data.totalCount;
1850
1851		//	録画予約が可能な日数
1852		var recPossibleDate = getDateAfterXdays(new Date(),8);
1853
1854		if(pdata.length != 0){
1855			var count = 0;
1856			var limit = statusObj.limit;
1857			var ngwords = statusObj.ngwords;
1858			var ng_perfectmatching = statusObj.ng_perfectmatching;
1859
1860			//      var nowtime = new Date();
1861			//      nowYear = formatDate(nowtime, 'YYYY');
1862			//      nowMonth = formatDate(nowtime, 'MM');
1863			//      nowDay = formatDate(nowtime, 'DD');
1864
1865			//	APIの戻り値をNGワード処理して検索結果データを作成
1866			jQuery.each(pdata, function(key, val){
1867				if(count == limit)  return true;
1868				var title = val.title;
1869				var hasNG = hasNGwords(title,ngwords,ng_perfectmatching);						
1870				if(hasNG) return true;
1871
1872				var date = val.startTime.slice(0,4) + '/' + val.startTime.slice(4,6) + '/' + val.startTime.slice(6,8); // 放送日yyyy/mm/ddに
1873				var dateObj = new Date(date);
1874				var month = formatDate(dateObj, 'MM');
1875				var day = formatDate(dateObj, 'DD');
1876				var week = formatDate(dateObj, 'W');
1877
1878				var datestr = month+'月'+day+'日('+week+')';
1879				var datestr_single = Number(month)+'月'+Number(day)+'日('+week+')';
1880				var datestr_simple = month+'/'+day+'('+week+')';
1881				var datestr_simple_single = Number(month)+'/'+Number(day)+'('+week+')';
1882				var datestr_simple_single2 = Number(month)+'/'+Number(day)+'('+week+')';
1883
1884				var startTime_org = val.startTime;
1885				var endTime_org = val.endTime;
1886				var programId = val.programId;
1887				var startTime = val.startTime.slice(8,10) + ':' + val.startTime.slice(10,12);
1888				var endTime = val.endTime.slice(8,10) + ':' + val.endTime.slice(10,12);
1889				var channel_icon_id = channel_icon[val.channelName];
1890
1891				// NO ON AIR
1892				var onairTimeObj = checkThisProgramNowOnair(dateObj,val.startTime,val.endTime);
1893				var nowonair = onairTimeObj.nowonair;
1894				var todayonair = onairTimeObj.todayonair;
1895
1896				// 番組ステータス
1897				var attr = val.attr;
1898				// var live = (-1 !== attr.indexOf('live'));
1899				// var first = (-1 !== attr.indexOf('first'));
1900				// var repeat = (-1 !== attr.indexOf('rep'));
1901				// var duo = (-1 !== attr.indexOf('duo'));
1902				// var free = (-1 !== attr.indexOf('free'));
1903				var live   = attr.includes('live');
1904				var first  = attr.includes('first');
1905				var repeat = attr.includes('rep');
1906				var duo    = attr.includes('duo');
1907				var free   = attr.includes('free');
1908
1909				var obj = {
1910					programId:programId,
1911					date:datestr,
1912					datestr:date,
1913					datestr_single:datestr_single,
1914					datestr_simple:datestr_simple,
1915					datestr_simple_single:datestr_simple_single,
1916					datestr_simple_single2:datestr_simple_single2,
1917					startTime_org:val.startTime,
1918					endTime_org :val.endTime,
1919					startTime:startTime,
1920					endTime:endTime,
1921					channelName:val.channelName,
1922					channelType:val.channelType,
1923					channelLogoUrl:val.channelLogoUrl,
1924					serviceCode:val.serviceCode,
1925					eventId:val.eventId,
1926					rec:val.rec,
1927					programDate:val.programDate,
1928					url:val.url,
1929					title:title,
1930					nowonair:nowonair,
1931					todayonair:todayonair,
1932					airTime:val.airTime,
1933					attr:attr,
1934					live:live,
1935					first:first,
1936					repeat:repeat,
1937					duo:duo,
1938					free:free,
1939					channelNo:val.channelNo,
1940					//						genreIds:val.genreIds,
1941					//photo:val.photo,
1942					summary:val.summary,
1943					tags:val.tags,
1944					genreIds:val.genreIds,
1945					isRecommend:val.isRecommend,
1946					isFreeCa:val.isFreeCa,
1947					minogashiFlg:val.minogashiFlg,
1948					course:val.course,
1949				};
1950
1951				if(getImage == 1 && val.photo.length != 0){
1952					obj.photo = 'https://tvguide.myjcom.jp/'+val.photo[0].photo;
1953					obj.copyright = val.photo[0].copyright;
1954					obj.hasPhoto = true;
1955				}else{
1956					obj.photo = '/special/common/images/no_image_800x448.jpg';
1957					obj.copyright = '';
1958					obj.hasPhoto = false;
1959				}
1960
1961				//	予約可能日程かチェック   
1962				if(recPossibleDate <= new Date(date)){
1963					obj.rec = false;
1964				}else{
1965					obj.rec = true;
1966				}
1967
1968				result.push(obj);
1969				count++;
1970			});//jQuery.each
1971
1972			// trace("追加したresult");
1973			// trace(result);
1974
1975		}else{
1976			//    検索結果なし
1977			result = ['検索結果はありません'];    
1978			load_status = 1;
1979		}
1980	}).fail(function(data){  // Ajaxリクエストが失敗した時発動
1981		result = ["APIエラー:"+data.errorMassage];    
1982		load_status = 2;
1983		trace("番組表API(jcom_api):FAIL "+result);
1984
1985	}).always(function(data){  // Ajaxリクエストが成功・失敗どちらでも発動
1986		//trace("番組表API(jcom_api):ALWAYS");
1987		/**
1988		trace(searchObj);
1989		trace(statusObj);
1990		trace(data);
1991		//*/
1992
1993		statusObj.api_type = 'program';
1994		searchObj.searchBtnURL = getSearchProgramBtnURL(searchObj);
1995		if(callback != null) parent[callback](result,load_status,searchObj,statusObj);
1996	});
1997
1998}
1999
2000/*--------------------------------------------------------------
2001	配列に含まれるかチェック
2002--------------------------------------------------------------*/
2003function checkIncludedInArr(arr,val){
2004	//arr.indexOf(val);
2005	arr.includes(val);
2006}
2007
2008/*--------------------------------------------------------------
2009	番組表API:NGワード
2010--------------------------------------------------------------*/
2011//	配列に値がふくまれるかチェック
2012function hasNGwords(val,arr,perfectmatching){
2013	var flag = false;
2014	var len = arr.length;
2015	if(perfectmatching){
2016		for(var i=0;i<len;i++){
2017			if(val == arr[i]){
2018				flag = true;
2019				continue;
2020			}
2021		}//	for
2022	}else{
2023		// for(var i=0;i<len;i++){
2024		// 	if (val.indexOf(arr[i]) != -1) {
2025		// 		flag = true;
2026		// 		continue;
2027		// 	}
2028		// }//	for
2029		for (let i = 0; i < len; i++) {
2030			if (val.includes(arr[i])) {
2031				flag = true;
2032				continue;
2033			}
2034		}
2035	}
2036	return flag;
2037}
2038/*--------------------------------------------------------------
2039	番組表API:NGジャンルID
2040--------------------------------------------------------------*/
2041//	配列に値がふくまれるかチェック
2042function hasNGGenreIDCheck(val,ng_genreid){
2043	//trace("------------------------------------")
2044	//	val	 //	32
2045	//	ng	 //	31,60,6F
2046	
2047	
2048	var flag = false;
2049	var count = 0;
2050	
2051	var len = ng_genreid.length;
2052	
2053	//trace(val+" / "+ng_genreid);
2054	
2055	for(var i=0;i<len;i++){
2056		
2057		var val_len = val.length;
2058		
2059		for(var v=0;v<val_len;v++){
2060			var id = val[v];
2061			//trace(id+" : "+ng_genreid[i]);
2062			
2063			if(id == ng_genreid[i]){
2064				flag = true;
2065				continue;
2066			}
2067		}//	for
2068		
2069	}//	for
2070	
2071
2072	return flag;
2073}
2074
2075/*--------------------------------------------------------------
2076	番組表API:もっとみるボタンのURL
2077	2020/1/22
2078--------------------------------------------------------------*/
2079function getSearchProgramBtnURL(searchObj){
2080	var query = (searchObj.query) ? "keyword="+searchObj.query : "";
2081	var genreId = (searchObj.genreId) ? "&genre="+searchObj.genreId : "";
2082	var queryTypeID = (searchObj.queryType) ? searchObj.queryType : "";
2083	var queryType = "";
2084	
2085	if(queryTypeID == 1){
2086		queryType = "&keywordType=or";
2087	}
2088	
2089	var targetChannels = "";
2090	var channel = "";
2091	
2092	//trace("searchObj.targetChannels "+searchObj.targetChannels);
2093	
2094	if(searchObj.targetChannels != null){
2095		targetChannels = getTargetChannelsQuery(searchObj.targetChannels);
2096	}else if(searchObj.serviceCode != null){
2097		channel = '&channel='+searchObj.serviceCode;
2098	}
2099	
2100	var keywordType = "";
2101	if(searchObj.queryType){
2102		keywordType = (searchObj.queryType == 0) ? "&keywordType=and" : "&keywordType=or";
2103	}
2104	
2105	var queryTarget = "";
2106	if(searchObj.queryTarget){
2107		if(searchObj.queryTarget == 1){
2108			queryTarget = '&keywordTarget=title';
2109		}else if(searchObj.queryTarget == 2){
2110			queryTarget = '&keywordTarget=detail';
2111		}
2112	}
2113	
2114	var url = "https://tvguide.myjcom.jp/search/event/?"+query+targetChannels+genreId+channel+keywordType+queryTarget;
2115	//if(isStage) url = "https://stage-tvguide.myjcom.jp/search/event/?"+query+targetChannels+genreId+channel+keywordType;
2116
2117	return encodeURI(url);
2118}
2119
2120
2121/*==============================================
2122	
2123	2019/10/28
2124	オンデマンドAPI(VOD)
2125	
2126	//	APIパラメータ
2127	var searchObj = {
2128		category:'jmc/v200904/anime',
2129		//keyword:'宇宙',	//	検索ワード	半角スペース区切りで複数設定可能
2130		limit:10,	//	検索結果数 50以下
2131		flagInitialEpisodeOnly:1,	//	シリーズの表示 0(すべて表示:初期設定)、1(シリーズ作品単位、第一回のエピソードのみ表示)
2132		kindHishinbi:0,	//	配信日種別 0(すべて表示:初期設定)、1(新着限定)、2(まもなく配信)、3(もうすぐ終了)
2133		flagOr:0,	//	検索方法 0(and検索:初期設定)、1(or検索)
2134		flagMuryo:0,	//無料作品 0(全ての作品:初期設定)、1(無料作品)
2135		page:pageID,	//出力ページ数
2136		sort:3,	// ソート 1: 配信日(昇順) 2: 配信日(降順) 3: 作品名(昇順) 4: 作品名(降順)
2137		r18:0	//R18 0(非表示:初期設定)、1(表示
2138	};
2139	
2140	//	制御用パラメータ
2141	var statusObj = {
2142		uid:0,	//	UID
2143		//apiURL: 'https://adult-jvod.myjcom.jp/retrieveadult.jsonp',// アダルト用リクエストURL
2144		//apiURL: 'https://jvod.myjcom.jp/retrieve2.jsonp',// テスト用リクエストURL
2145		container:$('.ondemand_api_container'),		//番組表格納コンテナ デフォルト .ondemand_api_container 省略可
2146		ng_perfectmatching:false,	//	NGワードを完全一致とする(true)しない(false:デフォルト) 省略可
2147		ngwords:['宇宙'],	//	NGワード 配列で複数設定可能 省略可
2148		unuseNgWords:true,	//	NGワードをキャンセル(true)する、しない(false:デフォルト) 省略可
2149		callback:'searchOndemandAPICpmplete'	//	コールバック関数 デフォルト searchOndemandAPICpmplete 省略可
2150	};	
2151		
2152	//	データ呼び出し
2153	getJcomOndemandList(searchObj,statusObj);
2154	
2155==============================================*/
2156function getJcomOndemandList(_searchObj,_statusObj){
2157	setCurrentTimeForAPI();
2158	var requestURL;
2159	var statusObj = {};
2160	var limit,num;
2161	var ngwords,ng_perfectmatching,unuseNgWords;
2162	
2163	//	NGワードを使わない
2164	if(_statusObj.unuseNgWords != null){
2165		unuseNgWords = _statusObj.unuseNgWords;
2166	}else{
2167		unuseNgWords = false;
2168	}
2169	
2170	if(_searchObj.limit == null){
2171		_searchObj.limit = 10;
2172	}
2173	
2174	//	NGワード
2175	if(!unuseNgWords){
2176		if(_statusObj.ngwords != null){
2177			ngwords = _statusObj.ngwords.concat(defaultNGwords);
2178		}else{
2179			ngwords = defaultNGwords;
2180		}
2181		num = 50;
2182		limit = _searchObj.limit;
2183	}else{
2184		ngwords = [];
2185		limit = num = _searchObj.limit;
2186	}
2187	
2188	if(50 <= num) num = 50; // 検索可能なMAXは50まで。51からエラー
2189	
2190	//	利用するAPIのURL
2191	if(_statusObj.apiURL != null){
2192		statusObj.apiURL = _statusObj.apiURL;
2193	}else{
2194		statusObj.apiURL = "https://jvod.myjcom.jp/retrieve.jsonp";
2195	}
2196	
2197	// _searchObjからリクエストURLを作成
2198	var apiURL = statusObj.apiURL;//"https://jvod.myjcom.jp/retrieve2.jsonp";// "https://jvod.myjcom.jp/retrieve.jsonp";
2199	requestURL = apiURL+"?num="+num;
2200	
2201	if(_searchObj.category != null){
2202		requestURL += '&category='+_searchObj.category;
2203	}
2204	if(_searchObj.page != null){
2205		requestURL += '&page='+_searchObj.page;
2206	}
2207	if(_searchObj.keyword != null){
2208		requestURL += '&keyword='+_searchObj.keyword;
2209	}
2210	if(_searchObj.sort != null){
2211		requestURL += '&sort='+_searchObj.sort;
2212	}else{
2213		requestURL += '&sort=1';
2214	}
2215	if(_searchObj.flagSeries != null){
2216		requestURL += '&flagSeries='+_searchObj.flagSeries;
2217	}else{
2218		requestURL += '&flagSeries=0';
2219	}
2220	if(_searchObj.flagInitialEpisodeOnly != null){
2221		requestURL += '&flagInitialEpisodeOnly='+_searchObj.flagInitialEpisodeOnly;
2222	}else{
2223		requestURL += '&flagInitialEpisodeOnly=0';
2224	}
2225	if(_searchObj.kindHishinbi != null){
2226		requestURL += '&kindHishinbi='+_searchObj.kindHishinbi;
2227	}else{
2228		requestURL += '&kindHishinbi=0';
2229	}
2230	if(_searchObj.flagOr != null){
2231		requestURL += '&flagOr='+_searchObj.flagOr;
2232	}else{
2233		requestURL += '&flagOr=0';
2234	}
2235	if(_searchObj.flagMuryo != null){
2236		requestURL += '&flagMuryo='+_searchObj.flagMuryo;
2237	}else{
2238		requestURL += '&flagMuryo=0';
2239	}
2240	
2241		//	アセットIDでの検索時はその他項目は不要
2242	if(_searchObj.assetId != null){
2243		requestURL = apiURL+'?assetId='+_searchObj.assetId;
2244	}
2245	if(_searchObj.r18 != null){
2246		requestURL += '&r18='+_searchObj.r18;
2247	}else{
2248		requestURL += '&r18=0';
2249	}
2250	
2251	// _statusObjから制御用Objを抽出
2252	
2253	if(_statusObj.uid != null) statusObj.uid = _statusObj.uid;
2254	if(_statusObj.container != null){
2255		statusObj.container = _statusObj.container;
2256	}else{
2257		statusObj.container = '.ondemand_api_container';
2258	}
2259	if(_statusObj.container_parent != null){
2260		statusObj.container_parent = _statusObj.container_parent;
2261	}
2262	if(_statusObj.ng_perfectmatching != null){
2263		ng_perfectmatching = _statusObj.ng_perfectmatching;
2264	}else{
2265		ng_perfectmatching = false;
2266	}
2267	if(_statusObj.callback != null){
2268		statusObj.callback = _statusObj.callback;
2269	}else{
2270		statusObj.callback = "searchOndemandAPICpmplete";
2271	}
2272		
2273	var result = [];
2274	var load_status;
2275	var count = 0;
2276	
2277	/**/
2278	trace("------------------------ VOD(jcom_api)")
2279	trace(_searchObj);
2280	trace(statusObj);
2281	trace(requestURL);
2282	/**/
2283
2284	
2285	$.ajax({
2286		url: requestURL,
2287		type:'GET',
2288		dataType: 'jsonp'
2289	}).done(function(data) {
2290		trace("VOD LOADED SUCCESS(jcom_api)");
2291		trace(data);
2292		if(data.status == -1) return;
2293		var resultN = data.total_count;
2294		statusObj.total_count = data.total_count;
2295		
2296		if(resultN != 0){
2297			//trace("検索結果あり "+resultN);		
2298			load_status = 0;
2299			var len = data.result.length;
2300			for(var i=0;i<len;i++){        
2301				if(count == limit)  continue;
2302				var title = data.result[i].Title;
2303				var hasNG = hasNGwords(title,ngwords,ng_perfectmatching);		
2304				
2305				if(hasNG) continue;
2306				result.push(data.result[i]);
2307				count++;
2308			}//    for
2309	
2310		}else{
2311			//trace("結果なしは枠ごと非表示");
2312			result = [];
2313			statusObj.searchBtnURL = vodsite;
2314			load_status = 1;
2315		}
2316	}).fail(function(data) {
2317		//trace("読み込み失敗(jcom_api)");
2318		//trace(data);
2319		result = [];
2320		statusObj.searchBtnURL = vodsite;
2321		load_status = 2;
2322	}).always(function(data) {
2323		//trace("処理完了(jcom_api) "+load_status);
2324		
2325		if(result.length == 0){
2326			sload_statustatus = 1;
2327			statusObj.searchBtnURL = vodsite;
2328		}else{
2329			statusObj.searchBtnURL = getMoreOndemandBtnURL(_searchObj);
2330		}
2331		
2332		statusObj.api_type = 'ondemand';
2333		var callback = statusObj.callback;
2334		if(callback != null) parent[callback](result,load_status,requestURL,statusObj,_searchObj);
2335	});
2336}
2337
2338/*--------------------------------------------------------------
2339	オンデマンドAPI:もっとみるボタンのURL
2340--------------------------------------------------------------*/
2341var vodsite = 'https://jvod.myjcom.jp/';
2342var isMoreOndemandBtn = true;
2343function getMoreOndemandBtnURL(searchObj){
2344	trace("●オンデマンドAPI:もっとみるボタンのURL ");
2345	var keyword = (searchObj.keyword) ? searchObj.keyword : "";
2346	var category = (searchObj.category) ? getOndemandCategoryQuery(searchObj.category) : '&genre=0&subgenre=none';
2347	var Haishinbi = (searchObj.kindHishinbi) ? searchObj.kindHishinbi : 0;
2348	var Haishinbi = (searchObj.kindHishinbi) ? searchObj.kindHishinbi : 0;
2349	
2350	//if(isStage) vodsite = 'https://stg-jvod.myjcom.jp/';
2351	var url = vodsite+"kensaku/search?&keyword="+keyword+category+"&Haishinbi="+Haishinbi+"&Device=0&Syllabary=0&categorysubcheck=&sub=検索";;
2352	
2353	// VODアプリ分岐 2019/12/09
2354
2355	if(typeof useJCOMLINK !== 'undefined'){
2356		trace("useJCOMLINK ["+useJCOMLINK+"]  ");
2357		if(useJCOMLINK == 'true'){
2358			url = 'https://linkvod.myjcom.jp/search?q='+keyword;
2359		}else{
2360			url = 'https://vod.myjcom.jp/video';
2361		}
2362	}else{
2363		trace("useJCOMLINK なし");
2364	}
2365	
2366	return encodeURI(url);
2367}
2368
2369
2370/*==============================================
2371	
2372	2019/10/28
2373	オンデマンドAPI(VOD)カラオケ
2374	
2375	//	APIパラメータ
2376	var searchObj = {
2377		singer:'',	// アーティスト名
2378		title:'',	// 楽曲名
2379		startPhrase:'',	// 歌い出し
2380		musicID:'',	// 楽曲の番号
2381		initialTitle:'',	// 楽曲名の先頭文字(ひらがな)
2382		initialSinger:'',	// アーティスト名の先頭文字(ひらがな)
2383		generation:'',	// 年代 4桁の数字2個を-でつなげたもの 例 2000-2010
2384		release_month:'',	// 配信月 例 201908
2385		order:'',	// 指定なし or 1:「アーティスト名」 昇順 2:「楽曲名」 昇順 3:「リリース日」 降順 4:「AssetId」 昇順
2386		LicensingmonthStart:'1',	// 配信開始日
2387		LicensingmonthEnd:'50',	// 配信終了日
2388		all:'u',	// 検索用文字列(楽曲名、アーティスト名の双方のOR検索を行う場合に利用する文字列
2389		page:'',	// 出力結果のページを指定する 数字(1以上、1000以下)
2390		num:'',	// 1ページ当たりの件数を指定する 数字(1以上、50以下)
2391		ie:'',	// ⼊⼒キーワードの⽂字コード ie:u: UTF-8 ie:s: Shift-JIS ie:e: EUC-JP 
2392		callback:'',	// JSONP のコールバック関数名 callback:関数名(例:callback:response_jcomvod)使⽤可能⽂字は、英数字およびアンダースコア。
2393	};
2394	
2395	//	制御用パラメータ
2396	var statusObj = {
2397		uid:0,	//	UID
2398		apiURL: 'https://jvod.myjcom.jp/retrievekaraoke.jsonp',// カラオケ用リクエストURL
2399		container:$('.karaoke_api_container'),		//格納コンテナ デフォルト .karaoke_api_container 省略可
2400		callback:'searchOndemandKaraokeAPICpmplete'	//	コールバック関数 デフォルト searchOndemandKaraokeAPICpmplete 省略可
2401	};	
2402		
2403	//	データ呼び出し
2404	getJcomOndemandKaraokeList(searchObj,statusObj);
2405	
2406==============================================*/
2407function getJcomOndemandKaraokeList(_searchObj,_statusObj){
2408	setCurrentTimeForAPI();
2409	var requestURL;
2410	var statusObj = {};
2411	var limit,num;
2412
2413	if(_searchObj.num == null){
2414		_searchObj.num = 10;
2415	}
2416
2417	if(50 <= num) num = 50; // 検索可能なMAXは50まで。51からエラー
2418	
2419	//	利用するAPIのURL
2420	if(_statusObj.apiURL != null){
2421		statusObj.apiURL = _statusObj.apiURL;
2422	}else{
2423		statusObj.apiURL = "https://jvod.myjcom.jp/retrievekaraoke.jsonp";
2424	}
2425	
2426	// _searchObjからリクエストURLを作成
2427	var apiURL = statusObj.apiURL;//"https://jvod.myjcom.jp/retrieve2.jsonp";// "https://jvod.myjcom.jp/retrieve.jsonp";
2428	requestURL = apiURL+"?num="+num;
2429	
2430	if(_searchObj.singer != null){
2431		requestURL += '&singer='+_searchObj.singer;
2432	}
2433	if(_searchObj.title != null){
2434		requestURL += '&title='+_searchObj.title;
2435	}
2436	if(_searchObj.startPhrase != null){
2437		requestURL += '&startPhrase='+_searchObj.startPhrase;
2438	}
2439	if(_searchObj.musicID != null){
2440		requestURL += '&musicID='+_searchObj.musicID;
2441	}
2442	if(_searchObj.initialTitle != null){
2443		requestURL += '&initialTitle='+_searchObj.initialTitle;
2444	}
2445	if(_searchObj.initialSinger != null){
2446		requestURL += '&initialSinger='+_searchObj.initialSinger;
2447	}
2448	if(_searchObj.generation != null){
2449		requestURL += '&generation='+_searchObj.generation;
2450	}
2451	if(_searchObj.release_month != null){
2452		requestURL += '&release_month='+_searchObj.release_month;
2453	}
2454	if(_searchObj.order != null){
2455		requestURL += '&order='+_searchObj.order;
2456	}
2457	if(_searchObj.LicensingmonthStart != null){
2458		requestURL += '&LicensingmonthStart='+_searchObj.LicensingmonthStart;
2459	}
2460	if(_searchObj.LicensingmonthEnd != null){
2461		requestURL += '&LicensingmonthEnd='+_searchObj.LicensingmonthEnd;
2462	}
2463	if(_searchObj.all != null){
2464		requestURL += '&all='+_searchObj.all;
2465	}
2466	if(_searchObj.page != null){
2467		requestURL += '&page='+_searchObj.page;
2468	}
2469	if(_searchObj.num != null){
2470		requestURL += '&num='+_searchObj.num;
2471	}
2472	if(_searchObj.ie != null){
2473		requestURL += '&ie='+_searchObj.ie;
2474	}
2475	if(_searchObj.callback != null){
2476		requestURL += '&callback='+_searchObj.callback;
2477	}
2478
2479	// _statusObjから制御用Objを抽出
2480	
2481	if(_statusObj.uid != null) statusObj.uid = _statusObj.uid;
2482	if(_statusObj.container != null){
2483		statusObj.container = _statusObj.container;
2484	}else{
2485		statusObj.container = '.karaoke_api_container';
2486	}
2487	if(_statusObj.ng_perfectmatching != null){
2488		ng_perfectmatching = _statusObj.ng_perfectmatching;
2489	}else{
2490		ng_perfectmatching = false;
2491	}
2492	if(_statusObj.callback != null){
2493		statusObj.callback = _statusObj.callback;
2494	}else{
2495		statusObj.callback = "searchOndemandAPICpmplete";
2496	}
2497		
2498	var result = [];
2499	var load_status;
2500	var count = 0;
2501	
2502	/**/
2503	trace("------------------------ VOD KARAOKE(jcom_api)")
2504	trace(_searchObj);
2505	trace(statusObj);
2506	trace(requestURL);
2507	/**/
2508
2509	
2510	$.ajax({
2511		url: requestURL,
2512		type:'GET',
2513		dataType: 'jsonp'
2514	}).done(function(data) {
2515		trace("VOD KARAOKE LOADED SUCCESS(jcom_api)");
2516	
2517		if(data.status == -1) return;
2518		
2519		var resultN = data.total_count;
2520		statusObj.total_count = data.total_count;
2521		if(resultN != 0){
2522			load_status = 0;
2523			var len = data.result.length;
2524			for(var i=0;i<len;i++){        
2525				result.push(data.result[i]);
2526				count++;
2527			}//    for
2528	
2529		}else{
2530			//trace("結果なしは枠ごと非表示");
2531			result = [];
2532			load_status = 1;
2533		}
2534	}).fail(function(data) {
2535		//trace("読み込み失敗(jcom_api)");
2536		//trace(data);
2537		result = [];
2538		load_status = 2;
2539	}).always(function(data) {
2540		//trace("処理完了(jcom_api) "+load_status);
2541		
2542		if(result.length == 0){
2543			load_status = 1;
2544		}
2545		
2546		var callback = statusObj.callback;
2547		statusObj.api_type = 'ondemand_karaoke';
2548		if(callback != null) parent[callback](result,load_status,requestURL,statusObj,_searchObj);
2549	});
2550}
2551
2552/*--------------------------------------------------------------
2553
2554	2017/11/9
2555	utils
2556
2557--------------------------------------------------------------*/
2558//	テスト出力用
2559var outputHTML = '';
2560function output(obj){
2561	var html = outputHTML+"<br />------------------------<br />";
2562	for (var key in obj){
2563		html += key + " = " + obj[key] + "<br />";
2564    }
2565	outputHTML += html;
2566	$('.output').html(html);
2567}
2568
2569//	dateObjから、addDays日後の日付を取得
2570function getDateAfterXdays(dateObj, addDays) {
2571	var dt = dateObj;
2572	var baseSec = dt.getTime();
2573	var addSec = addDays * 86400000;//日数 * 1日のミリ秒数
2574	var targetSec = baseSec + addSec;
2575	dt.setTime(targetSec);
2576	return dt;
2577}
2578// 全角、半角の混じった文字列をバイト数でトリミング
2579function trimTextByBite(str,trimNum) {
2580	////trace("trimTextByBite--------------------- "+str);
2581	var afterTxt = '&hellip;';
2582	var result;
2583	var txt ="";
2584	var textLength = 1;
2585    var r = 0; 
2586    for (var i = 0; i < str.length; i++) { 
2587        var c = str.charCodeAt(i); 
2588        if ( (c >= 0x0 && c < 0x81) || (c == 0xf8f0) || (c >= 0xff61 && c < 0xffa0) || (c >= 0xf8f1 && c < 0xf8f4)) { 
2589            r += 1; 
2590        } else { 
2591            r += 2; 
2592        } 
2593		if(r < trimNum){
2594			textLength ++;
2595		}
2596    } 
2597	var textTrim = str.substr(0,(textLength));
2598	if(trimNum <= (textLength*2)) {
2599		result = textTrim + afterTxt;
2600	}else{
2601		result = str;
2602	}
2603    return result; 
2604} 
2605
2606
2607
2608/*=============================================
2609
2610	オンデマンドリンクの遷移 2019/11/1
2611	
2612=============================================*/
2613
2614function addJcomVODLnkEvent(){
2615	
2616	$('.section').off('click', '.vodapplink').on('click', '.vodapplink', function(e){
2617		e.preventDefault();
2618	
2619		var assetID = $(this).find('a').attr('href');
2620	
2621		if (checkNowDeviceOS() === 'other') {
2622			jumpToJcomVODURL(assetID);
2623		} else {
2624			setJcomVODDetails(assetID);
2625		}
2626		return false;
2627	});
2628
2629	$('.section').on({"mouseenter": function(){
2630		$(this).addClass('hover');
2631	},"mouseleave": function(){
2632		$(this).removeClass('hover');
2633	}}, ".vodlinkarea");
2634
2635}
2636
2637//アプリ詳細リンクモーダル
2638function setJCOMVODAppDetailModal(appUrl, storeUrl){
2639	trace("setJCOMVODAppDetailModal アプリ詳細リンクモーダル ");
2640	clickModalname = "modal_appdetail";
2641	$('.modal_appdetail .hasdata').show();
2642	$('.modal_appdetail .nodata').hide();
2643	
2644	$('.modal_appdetail .download a').attr('href',storeUrl);
2645	$('.modal_appdetail .openapp a').attr('href',appUrl);
2646	
2647	modalname = clickModalname;
2648	changeModalDetail();
2649	showModal();
2650}
2651
2652// アプリがインストール済なら詳細画面へ遷移、インストール未ならストアに遷移
2653function setJcomVODDetails(assetId){
2654	trace("details "+assetId);
2655	var os = checkNowDeviceOS();
2656	var query = assetId+"";
2657	
2658	if (os === 'ios'){
2659		if(getiOSVer() != 9){
2660			setJCOMVODAppDetailModal("jcomapp://jp.co.jcom.JcomApp/webview/contents/" + query, 'http://itunes.apple.com/jp/app/id449811083?mt=8');
2661		}else{
2662			setJCOMVODAppDetailModal("jcomapp://jp.co.jcom.JcomApp/webview/contents/" + query, 'http://itunes.apple.com/jp/app/id449811083?mt=8');
2663		}
2664		modalHasData = true;
2665	}else if(os === 'android'){
2666		// AndroidのChomeの時はインテント起動
2667		if (isNowBrowsers(['chrome'])){
2668			location.href = "intent://jp.co.jcom.JcomApp/webview/contents/" + assetId + "#Intent;scheme=jcomapp;package=jp.co.jcom.JcomApp;end";
2669		}else{
2670			launchJcomVODApp("jcomapp://jp.co.jcom.JcomApp/webview/contents/" + assetId, 'market://details?id=jp.co.jcom.JcomApp');
2671		}
2672	}else{
2673		jumpToJcomVODURL(assetId);
2674	}
2675}
2676function jumpToJcomVODURL(assetId){
2677	var url = 'https://jvod.myjcom.jp/detail/'+assetId;
2678	window.open( url, "_blank" );
2679}
2680
2681//	iOS
2682function launchJcomVODApp(appUrl, storeUrl){
2683	var iframe = document.createElement('iframe');
2684	iframe.style.visibility = "hidden";
2685	iframe.src = appUrl;
2686	document.body.appendChild(iframe);
2687
2688	var time = (new Date()).getTime();
2689
2690	setTimeout(function(){
2691		var now = (new Date()).getTime();
2692		document.body.removeChild(iframe);
2693		if((now-time)>400) {
2694			return;
2695		}
2696		document.location = storeUrl;
2697	}, 100);
2698}
2699// ブラウザ判定
2700var isNowBrowsers = function(browsers){
2701	var thusBrowser = getBrowser();
2702	for(var i=0; i<browsers.length; i++){
2703		if(browsers[i] == thusBrowser){
2704			return true;
2705			exit;
2706		}
2707	}
2708	return false;
2709};
2710
2711function checkNowDeviceOS(){
2712		// var userAgent = window.navigator.userAgent.toLowerCase();
2713		// os = null;
2714		// if(userAgent.indexOf('iphone') != -1){
2715		// 	os = 'ios';
2716		// }else if(userAgent.indexOf('ipad') != -1){
2717		// 	os = 'ios';
2718		// }else if(userAgent.indexOf('ipod') != -1){
2719		// 	os = 'ios';
2720		// }else if(userAgent.indexOf('android') != -1){
2721		// 	os = 'android';
2722		// }else{
2723		// 	os = 'other';
2724		// }
2725		var ua = navigator.userAgent.toLowerCase();
2726		var os = 'other';
2727
2728		if (ua.includes('iphone') || ua.includes('ipad') || ua.includes('ipod')) {
2729			os = 'ios';
2730		} else if (ua.includes('android')) {
2731			os = 'android';
2732		}
2733		return os;
2734	}
2735	
2736
2737
2738/*==============================================
2739	
2740	2021/11/16
2741	番組表マスターAPIの複数検索
2742	
2743/*==============================================*/
2744var masterApiSearchList;
2745var masterApiSearchResultList = [];
2746var masterApiStatusObj
2747var masterApiLoadedNum = 0;
2748var masterApiSearchCompleteCallback;
2749var masterApiSearchStatusList = [];
2750var masterApiMultiObjList = [];
2751var masterApiMultiObjUid = 0;
2752
2753function getJcomProgramMasterListMultiSearch(searchList,statusObj){
2754	trace("================================== 番組表マスターAPIの複数検索 "+statusObj.callback);
2755//	masterApiLoadedNum = 0;
2756//	masterApiSearchList = searchList;
2757//	masterApiStatusObj = statusObj;
2758//	masterApiSearchCompleteCallback = statusObj.callback;
2759//	statusObj.callback = "jcomProgramMasterMultiSearchLoaded";
2760	
2761	
2762	var masterApiMultiObj = {};
2763	masterApiMultiObj.loadNum = 0;
2764	masterApiMultiObj.loadTital = searchList.length;
2765	masterApiMultiObj.searchList = searchList;
2766	masterApiMultiObj.statusList = [];
2767	masterApiMultiObj.statusObj = statusObj;
2768	masterApiMultiObj.callback = statusObj.callback;
2769	masterApiMultiObj.resultList = [];
2770	masterApiMultiObjList.push(masterApiMultiObj);
2771	masterApiMultiObj.masterUid = masterApiMultiObjUid;
2772	
2773	statusObj.callback = "jcomProgramMasterMultiSearchLoaded";
2774	statusObj.masterUid = masterApiMultiObjUid;
2775	masterApiMultiObjUid++;
2776	
2777	var len = searchList.length;
2778	for(var i=0;i<len;i++){
2779		var searchObj = searchList[i];
2780		getJcomProgramMasterList(searchObj,statusObj);
2781	}//	for
2782	
2783}
2784
2785//	読み込み完了
2786function jcomProgramMasterMultiSearchLoaded(result,status,searchObj,statusObj){
2787	trace("番組表マスターAPIの複数検索:読み込み完了 "+status);
2788	trace(searchObj);
2789	trace(result);
2790	
2791	var len = masterApiMultiObjList.length;
2792	for(var i=0;i<len;i++){
2793		var masterApiMultiObj = masterApiMultiObjList[i];
2794
2795		if(statusObj.masterUid == masterApiMultiObj.masterUid){
2796			masterApiMultiObj.loadNum ++;
2797			masterApiMultiObj.statusList.push(status);
2798
2799			if(status == 0){
2800				var resultN = result.length;
2801				for(var v=0;v<resultN;v++){
2802					var obj = result[v];
2803					obj.alignment = searchObj.alignment;
2804					masterApiMultiObj.resultList.push(obj);
2805				}//	for
2806			}
2807
2808			if(masterApiMultiObj.loadNum == masterApiMultiObj.loadTital){
2809				jcomProgramMasterMultiSearchLoadedComplete(masterApiMultiObj);
2810			}
2811		}
2812	}//	for
2813
2814}//
2815
2816//	全て読み込み完了
2817function jcomProgramMasterMultiSearchLoadedComplete(masterApiMultiObj){
2818	trace("番組表マスターAPIの複数検索:全て読み込み完了 ");
2819
2820	var result;
2821	var status;
2822	
2823	if(masterApiMultiObj.resultList.length != 0){
2824		
2825		trace("元");
2826		trace(masterApiMultiObj.resultList);
2827		//	重複削除
2828		var list = filterUniqueItemsById(masterApiMultiObj.resultList);
2829//		trace("重複削除");
2830//		trace(list);
2831		
2832		// 放送日順に並べ替え
2833		list.sort(function(a,b) {
2834			return (new Date(a.next_dateObj) > new Date(b.next_dateObj) ? 1 : -1);
2835		});
2836		status = 0;
2837		result = list;
2838		
2839	}else{
2840		status = 1;
2841		result = "番組情報はありませんでした。";
2842	}
2843	
2844	var searchObj = masterApiMultiObj.searchList;//masterApiSearchList;
2845	var statusObj = masterApiMultiObj.statusObj;//masterApiStatusObj;
2846	var callback_func = masterApiMultiObj.callback;
2847	statusObj.api_type = 'master';
2848	
2849	if(callback_func != null) parent[callback_func](result,status,searchObj,statusObj);
2850}//
2851
2852//	重複を削除
2853function filterUniqueItemsById (array) {
2854  // idを集約した配列を作成
2855  const itemIds = array.map(function(item) {
2856    return item.programId;
2857  });
2858  // 
2859  return array.filter(function(item, index) {
2860    //return itemIds.indexOf(item.programId) === index;
2861	return itemIds.findIndex(id => id === item.programId) === index;
2862  });
2863}
2864
2865
2866/*==============================================
2867	
2868	2021/3/23
2869	番組表マスターAPI
2870/**
2871	//	APIパラメータ
2872	var searchObj = {
2873			//areaId:12,	// エリアID 省略可
2874			genreId:6,	// ジャンルID
2875			//keyword:'タモリ',	//	検索ワード APIではqueryで処理
2876			//limit:10,	//	検索結果数
2877			//targetChannels:'0,1',		//	検索対象の放送波 0(CATV)、1(コミュチャン)、2(BS)、3(地デジ)カンマ区切りで複数設定可
2878			//serviceCode:'561_65406,560_65406',	
2879			queryTarget:0,	//	検索対象 0(すべて:初期設定)、1(番組名)、2(番組内容) 省略可
2880      queryType:0,	//	0(and検索), 1(or検索)
2881			attr:null, // イベント属性 デフォルトなし
2882		
2883			//	2021/3/17 追加機能
2884			//optionChannel:0,// チャンネル種別 0(基本チャンネル) 1(オプションチャンネル)、指定無しの場合は、絞り込み無し
2885			//programId:'4716,547442', // プログラムIDを指定。カンマ区切りで複数指定可能。指定無しは絞り込み無し 集約されたマスタ情報が存在する場合は、親の番組マスタ情報を返却。
2886			//alignment:'new,feature,classic', //	番組マスタ管理画面から登録した任意文字列のフラグを指定する。カンマ区切りで複数指定可能。
2887			alignment_title:'BTS特集と年末年始一挙放送と年末年始特番',// フラグ名を表示する際の文言、設定ない場合はフラグそのまま。
2888			//hasExternalText:0,	// 0(すべて:初期設定) 1(追加コンテンツテキストありのみ) 番組マスタ管理画面から登録したテキストコンテンツが存在するマスタ情報を返却する。
2889			//hasExternalImage:0,	// 0(すべて:初期設定) 1(追加コンテンツ画像ありのみ) 番組マスタ管理画面から登録した画像コンテンツが存在するマスタ情報を返却する。
2890			//hasExternalVideo:0,	// 0(すべて:初期設定) 1(追加コンテンツ動画ありのみ) 番組マスタ管理画面から登録した動画コンテンツが存在するマスタ情報を返却する。
2891			//sort:0,	//	0(直近SI放送日時:初期設定)、1(番組マスタ名)、2(チャンネル)、3(ジャンル)
2892			//order:0,	//	0(昇順:初期設定)、1(降順)
2893			hasNextSi:0,	// 直近放送の有無	0(すべて:初期設定) 1(直近放送情報有りのみ) 直近放送情報が存
2893在する番組マスタを返却する。
2894		};	
2895		
2896	//	制御用パラメータ
2897	var statusObj = {
2898			uid:0,	//	UID
2899			container:'.program_master_api_container',		//番組表格納コンテナ(.付きの文字列で指定)デフォルト:.tv_program_list 省略可
2900			//container_parent:'.section_programlist',	// [Bランクでは設定NG!] 検索結果がない場合やエラー発生時、非表示にするエリア(.付きの文字列で指定)デフォルト:.section_relation_program .content_program(Bランク用)
2901			ng_genreid:'31,60',	//	指定したジャンルIDを除外
2902			ng_perfectmatching:false,	//	NGワードを完全一致とする(true)しない(false:デフォルト) 省略可
2903			nodata_hide:true,	//	検索結果がない場合やエラー発生時、エリアごと非表示にする(true:デフォルト)しない(false) 省略可
2904			displayN:10,	//	もっと見るボタンを表示。指定数ずつ番組を表示する 省略可
2905			callback:'jcomProgramMasterAPIComplete',	//	コールバック関数 デフォルト:searchProgramAPIComplete 省略可
2906			useRecommend:0,// おすすめ番組フラグを利用 0(しない:デフォルト),1(する)
2907		};	
2908		
2909	//	データ呼び出し
2910	getJcomProgramMasterList(searchObj,statusObj);
2911	
2912/*==============================================*/
2913
2914//var defaultNGwords = ['番組案内','番組ガイド','メガパックで配信中!'];
2915
2916function getJcomProgramMasterList(_searchObj,_statusObj){
2917	trace("番組表マスターAPI (jcom_api.js)");
2918	setCurrentTimeForAPI();
2919	trace(_searchObj);
2920	var user_area_id = jQuery.cookie("area_id");
2921	if(user_area_id == undefined){
2922		user_area_id = 12;
2923	}
2924	var searchObj = {};
2925	var statusObj = {};
2926	
2927	// _searchObjからAPI検索用Objを抽出
2928	
2929	//	2021/4/1追加
2930	if(_searchObj.hasNextSi != null){
2931		searchObj.hasNextSi =  _searchObj.hasNextSi;
2932	}
2933	//	2021/3/18追加
2934	if(_searchObj.optionChannel != null){
2935		searchObj.optionChannel =  _searchObj.optionChannel;
2936	}
2937	if(_searchObj.programId != null){
2938		searchObj.programId =  _searchObj.programId;
2939	}
2940	if(_searchObj.alignment != null){
2941		searchObj.alignment =  _searchObj.alignment;
2942	}
2943	if(_searchObj.alignment_title != null){
2944		searchObj.alignment_title =  _searchObj.alignment_title;
2945	}else{
2946		searchObj.alignment_title =  _searchObj.alignment;
2947	}
2948	if(_searchObj.hasExternalText != null){
2949		searchObj.hasExternalText =  _searchObj.hasExternalText;
2950	}
2951	if(_searchObj.hasExternalImage != null){
2952		searchObj.hasExternalImage =  _searchObj.hasExternalImage;
2953	}
2954	if(_searchObj.hasExternalVideo != null){
2955		searchObj.hasExternalVideo =  _searchObj.hasExternalVideo;
2956	}
2957	if(_searchObj.sort != null){
2958		searchObj.sort =  _searchObj.sort;
2959	}
2960	if(_searchObj.order != null){
2961		searchObj.order =  _searchObj.order;
2962	}
2963	if(_searchObj.attr != null){
2964		searchObj.attr =  _searchObj.attr;
2965	}
2966	if(_searchObj.adult != null){
2967		searchObj.adult =  _searchObj.adult;
2968	}else{
2969		searchObj.adult = 0;
2970	}
2971	if(_searchObj.attr != null){
2972		searchObj.attr =  _searchObj.attr;
2973	}
2974
2975	if(_searchObj.areaId != null){
2976		searchObj.areaId =  _searchObj.areaId;
2977	}else{
2978		searchObj.areaId = user_area_id;
2979	}
2980
2981	if(_searchObj.limit != null){
2982		searchObj.limit = 100;
2983		statusObj.limit = _searchObj.limit;
2984	}else{
2985		searchObj.limit = 1000;
2986		statusObj.limit = 1000;
2987	}
2988
2989	if(_searchObj.keyword != null){
2990    searchObj.query = _searchObj.keyword;
2991    searchObj.keyword = _searchObj.keyword;
2992	}
2993	
2994	if(_searchObj.genreId != null){
2995		if(_searchObj.genreId != 'null'){
2996			searchObj.genreId = encodeURI(_searchObj.genreId);
2997			if(searchObj.keyword == ""){
2998			searchObj.keyword = getProgramAPIGenrIDName(searchObj.genreId);
2999			//trace(searchObj.genreId+"  searchObj.keyword "+searchObj.keyword);
3000			};
3001		}
3002	}
3003
3004	//	放送波の設定あればチャンネル設定無効
3005	if(_searchObj.targetChannels != null){
3006		//trace("_searchObj.targetChannels ある "+_searchObj.targetChannels);
3007		searchObj.targetChannels = _searchObj.targetChannels;
3008		
3009		var targetChannels_arr = _searchObj.targetChannels.split(',');
3010		var wavename = "";
3011		if(1 < targetChannels_arr.length){
3012			
3013			for(var i=0;i<targetChannels_arr.length;i++){			
3014				if(i < 4){
3015					if(i != 0) wavename += " / ";
3016					wavename += getTargetChannelTypeByID(targetChannels_arr[i]);	
3017				}
3018			}//	for				
3019		}else{
3020			wavename = getTargetChannelTypeByID(_searchObj.targetChannels);
3021		}
3022		if(searchObj.keyword == "") searchObj.keyword = wavename;
3023	
3024	}else{
3025		if(_searchObj.serviceCode != null){
3026			//trace("_searchObj.serviceCode ある "+_searchObj.serviceCode);
3027			
3028			searchObj.serviceCode = _searchObj.serviceCode;
3029			var serviceCode_arr = _searchObj.serviceCode.split(',');
3030			var chname = "";
3031			if(1 < serviceCode_arr.length){
3032				
3033				for(var i=0;i<serviceCode_arr.length;i++){			
3034					if(i < 3){
3035						if(i != 0) chname += " / ";
3036						chname += getChannelNameByServiceCode(serviceCode_arr[i]);					
3037					}else if(i == 3){
3038						chname += " などのチャンネル";
3039					}
3040				}//	for				
3041			}else{
3042				chname = getChannelNameByServiceCode(_searchObj.serviceCode);
3043			}
3044			
3045			if(searchObj.keyword == "") searchObj.keyword = chname;
3046		}
3047	}
3048	
3049	if(_searchObj.queryType != null){
3050		searchObj.queryType = Number(_searchObj.queryType);
3051	}else{
3052		searchObj.queryType = 0;
3053	}
3054	
3055	if(_searchObj.queryTarget != null){
3056		searchObj.queryTarget = _searchObj.queryTarget;
3057	}else{
3058		searchObj.queryTarget = 0;
3059	}
3060	
3061	// _statusObjから制御用Objを抽出
3062	
3063	if(_statusObj.uid != null) statusObj.uid = _statusObj.uid;
3064	if(_statusObj.masterUid != null) statusObj.masterUid = _statusObj.masterUid;
3065	
3066	if(_statusObj.container != null){
3067		statusObj.container = _statusObj.container;
3068	}else{
3069		statusObj.container = '.program_master_list';
3070	}
3071	if(_statusObj.container_parent != null){
3072		statusObj.container_parent = _statusObj.container_parent;
3073	}else{
3074		statusObj.container_parent = '.section .content_programmaster';
3075	}
3076	if(_statusObj.callback != null){
3077		statusObj.callback = _statusObj.callback;
3078	}else{
3079		statusObj.callback = "searchProgramAPIComplete";
3080	}
3081	if(_statusObj.research != null){
3082		statusObj.research = _statusObj.research;
3083	}else{
3084		statusObj.research = false;
3085	}
3086	if(_statusObj.nodata_hide != null){
3087		statusObj.nodata_hide = _statusObj.nodata_hide;
3088	}else{
3089		statusObj.nodata_hide = true;
3090	}
3091	if(_statusObj.noimage != null){
3092		statusObj.noimage = _statusObj.noimage;
3093	}else{
3094		statusObj.noimage = '/special/common/images/no_image_800x448.jpg';
3095	}
3096	if(_searchObj.title != null){
3097		searchObj.keyword = _searchObj.title;
3098	}
3099	
3100	if(searchObj.keyword == "") searchObj.keyword = "検索条件なし";
3101
3102	//	もっと見るボタンでの表示数
3103	if(_statusObj.displayN != null){
3104		statusObj.displayN = _statusObj.displayN;
3105	}
3106	
3107	//	もっと見るボタンでの表示数
3108	if(_statusObj.useRecommend != null){
3109		statusObj.useRecommend = _statusObj.useRecommend;
3110	}else{
3111		statusObj.useRecommend = 0;
3112	}
3113
3114	//	NGワード追加
3115	if(_statusObj.ngwords != undefined){
3116		statusObj.ngwords = _statusObj.ngwords;
3117		} else {
3118		statusObj.ngwords = [];
3119	}
3120	
3121	if(_statusObj.ng_perfectmatching != null){
3122		statusObj.ng_perfectmatching = _statusObj.ng_perfectmatching;
3123	}else{
3124		statusObj.ng_perfectmatching = false;
3125	}
3126	//	NGチャンネル
3127	if(_statusObj.ng_channels != undefined){
3128		statusObj.ng_channels = _statusObj.ng_channels;
3129	} else {
3130		statusObj.ng_channels = [];
3131	}
3132	//	NGジャンルID
3133	if(_statusObj.ng_genreid != undefined){
3134		statusObj.ng_genreid = _statusObj.ng_genreid;
3135	} else {
3136    statusObj.ng_genreid = [];
3137	}
3138	// コールバックパラメータ名の指定
3139	jsonpCallbackUID ++;
3140	statusObj.jsonpCallback = 'search_program'+jsonpCallbackUID;
3141
3142	searchJCOMProgramMasterAPI(searchObj,statusObj);
3143}
3144
3145//function isArray(obj) {
3146//    return Object.prototype.toString.call(obj) === '[object Array]';
3147//}
3148/*--------------------------------------------------------------
3149	番組表マスターAPI:検索
3150--------------------------------------------------------------*/
3151function searchJCOMProgramMasterAPI(searchObj,statusObj){
3152	trace('番組表マスターAPI(jcom_api):検索');
3153	var result = [];
3154	var message = "";
3155	var dataType = "jsonp";
3156	var jsonpCallback = statusObj.jsonpCallback;
3157	var url = "https://tvguide.myjcom.jp/api/getProgramMaster/?"; 
3158	var alignment_title = searchObj.alignment_title;
3159
3160	if(isMyjcom){
3161		url += getAPIRequestQuery(searchObj,false);
3162		//trace("番組表マスターAPI(jcom_api):myjcom "+url);
3163	}else{
3164		var param = getAPIRequestQuery(searchObj,true);
3165		url = api_php_path+'wrp='+jsonpCallback+'&url='+url+param;
3166		url = location.protocol+"//"+location.host+url;	// ローカルからアクセスできるよう絶対パスで指定
3167		//trace("番組表マスターAPI(jcom_api):other "+url);
3168	}
3169
3170	var callback = statusObj.callback;
3171	var load_status;
3172
3173	$.ajax({
3174		url: url,
3175		type:'POST',
3176		dataType: dataType,
3177		jsonpCallback: jsonpCallback
3178	}).done(function(data){ // Ajaxリクエストが成功した時発動
3179		trace("番組表マスターAPI(jcom_api):DONE");
3180		trace(data);
3181
3182		if(data === undefined) {
3183			result = ['検索失敗(data === undefined)'];    
3184			load_status = 2;
3185			trace("検索失敗(番組表マスターAPI(jcom_api):DONE)"+result);
3186			return;
3187		}
3188
3189		data.totalCount = statusObj.totalCount;
3190		trace("data.totalCount "+data.totalCount);
3191
3192		load_status = data.status;
3193		if(load_status != 0) return;
3194		var pdata = data.programMst;
3195		trace(pdata);
3196
3197		//	録画予約が可能な日数
3198		//    var recPossibleDate = getDateAfterXdays(new Date(),8);
3199
3200		trace("pdata.length "+pdata.length);
3201
3202		if(pdata.length != 0){
3203			var count = 0;
3204			var limit = statusObj.limit;
3205			var ngwords = statusObj.ngwords;// NGワード
3206			var ng_channels = statusObj.ng_channels;// NGチャンネル
3207			var ng_perfectmatching = statusObj.ng_perfectmatching;
3208			var ng_genreid = statusObj.ng_genreid;// NGジャンルID
3209
3210			//	検索結果データを作成
3211			jQuery.each(pdata, function(key, val){
3212
3213				if(count == limit)  return true;
3214
3215				var programId = val.programId;
3216				var title = val.title;
3217
3218				// NGワード(タイトル)
3219				var hasNG = hasNGwords(title,ngwords,ng_perfectmatching);
3220				if(hasNG) return true;
3221
3222				var channels = val.channels;
3223				var serviceCode = val.channels[0].serviceCode;
3224				var channelType = val.channels[0].channelType;
3225				var channelNo = val.channels[0].channelNo;
3226				var channelName = val.channels[0].channelName;
3227				var channelLogoUrl = val.channels[0].channelLogoUrl;
3228
3229				// NGチャンネル
3230				var hasNGChannel = hasNGwords(channelName,ng_channels,ng_perfectmatching);					
3231				if(hasNGChannel) return true;
3232
3233				//					if(35 < key && key < 39){
3234				// NGジャンルID
3235				var hasNGGenreID = false;
3236				if(ng_genreid.length != 0){
3237				hasNGGenreID = hasNGGenreIDCheck(val.genreIds,ng_genreid);
3238				//trace(val.genreIds+"  hasNGGenreID "+hasNGGenreID +"  "+title);
3239				if(hasNGGenreID) return true;
3240				}
3241				//
3242				//					}
3243
3244				var genreIds = val.genreIds;
3245				var summary = val.summary;
3246				var url = val.url;
3247				var attr = val.attr;
3248				// 番組ステータス
3249				// var live = (-1 !== attr.indexOf('live'));
3250				// var first = (-1 !== attr.indexOf('first'));
3251				// var repeat = (-1 !== attr.indexOf('rep'));
3252				// var duo = (-1 !== attr.indexOf('duo'));
3253				// var free = (-1 !== attr.indexOf('free'));
3254
3255				var live   = attr.includes('live');
3256				var first  = attr.includes('first');
3257				var repeat = attr.includes('rep');
3258				var duo    = attr.includes('duo');
3259				var free   = attr.includes('free');
3260
3261				var photos = val.photos;
3262				var photo = (photos[0]) ? val.photos[0].photo : statusObj.noimage;
3263				var copyright = (photos[0]) ? val.photos[0].copyright : '';
3264
3265				var externalText = val.externalText;
3266				var externalTextTitle = (externalText[0]) ? val.externalText[0].title : false;
3267				var externalTextContent = (externalText[0]) ? val.externalText[0].content : false;
3268				var externalImage = val.externalImage;
3269				var externalImageUrl = (externalImage[0]) ?  val.externalImage[0].url: false;
3270				var externalVideo = val.externalVideo;
3271				var embed = (externalVideo[0]) ?  val.externalVideo[0].embed: false;
3272				var warningMessage = val.warningMessage;
3273				var errorCode = val.errorCode;
3274				var errorMessage = val.errorMessage;
3275
3276				// 直近の番組スケジュール
3277				var next_dateObj,next_date,next_date_short;
3278				var hasNextTime = false;
3279				var nextStartTime = val.nextStartTime;
3280				if(hasNextTime != undefined){
3281					next_dateObj = YYYYMMDDhhmmssToDateObj(nextStartTime);
3282					next_date = formatDate(next_dateObj, 'YYYY年MM月DD日(W)hh:mm');
3283					next_date_short  = formatDate(next_dateObj, 'MM/DD(W) hh:mm');
3284
3285					var next_date_short_arr = next_date_short.split('/');
3286					var short_year = Number(next_date_short_arr[0]);
3287
3288					//trace("short_year "+short_year);
3289					var short_month_arr = next_date_short_arr[1].split('(');
3290					var short_month = Number(short_month_arr[0]);
3291					next_date_short = short_year+"/"+short_month+'('+short_month_arr[1];
3292					hasNextTime = true;
3293				}
3294
3295				var end_dateObj,end_date,end_time;
3296				var hasEndTime = false;
3297				var nextEndTime = val.nextEndTime;
3298				if(nextEndTime != undefined){
3299					end_dateObj = YYYYMMDDhhmmssToDateObj(nextEndTime);
3300					end_date = formatDate(end_dateObj, 'MM月DD日(W)hh:mm');
3301					end_time = formatDate(end_dateObj, 'hh:mm');
3302					hasEndTime = true;
3303				}
3304
3305				//
3306				var onairTimeObj = checkThisProgramNowOnair(next_dateObj,nextStartTime,nextEndTime);
3307				var nowonair = onairTimeObj.nowonair;
3308				var todayonair = onairTimeObj.todayonair;
3309
3310				var obj = {
3311					programId:programId,
3312					title:title,
3313					channels:channels,
3314					serviceCode:serviceCode,
3315					channelType:channelType,
3316					channelNo:channelNo,
3317					channelName:channelName,
3318					channelLogoUrl:channelLogoUrl,
3319					genreIds:genreIds,
3320					summary:summary,
3321					url:url,
3322					attr:attr,
3323					live:live,
3324					first:first,
3325					repeat:repeat,
3326					duo:duo,
3327					free:free,
3328					photos:photos,
3329					photo:photo,
3330					copyright:copyright,
3331					externalText:externalText,
3332					externalTextTitle:externalTextTitle,
3333					externalTextContent:externalTextContent,
3334					externalImage:externalImage,
3335					externalImageUrl:externalImageUrl,
3336					externalVideo:externalVideo,
3337					embed:embed,
3338					warningMessage:warningMessage,
3339					errorCode:errorCode,
3340					errorMessage:errorMessage,
3341					nextStartTime:nextStartTime,
3342					nextEndTime:nextEndTime,
3343					next_date:next_date,
3344					next_date_short:next_date_short,
3345					end_date:end_date,
3346					next_dateObj:next_dateObj,
3347					end_dateObj:end_dateObj,
3348					hasNextTime:hasNextTime,
3349					hasEndTime:hasEndTime,
3350					end_time:end_time,
3351					alignment_title:alignment_title,
3352					nowonair:nowonair,
3353					todayonair:todayonair
3354				};
3355
3356
3357				result.push(obj);
3358
3359				count++;
3360			});//jQuery.each
3361			//*/
3362		}else{
3363		//    検索結果なし
3364			result = ['検索結果はありません'];    
3365			load_status = 1;
3366		}
3367
3368	}).fail(function(data){  // Ajaxリクエストが失敗した時発動
3369		result = ["APIエラー:"+data.errorMassage];    
3370		load_status = 2;
3371		trace("番組表マスターAPI(jcom_api):FAIL "+result);
3372
3373	}).always(function(data){  // Ajaxリクエストが成功・失敗どちらでも発動
3374		/**/
3375		trace("番組表マスターAPI(jcom_api):ALWAYS");
3376		trace(searchObj);
3377		trace(statusObj);
3378		trace(result);
3379		//trace(data);
3380		//*/
3381		searchObj.searchBtnURL = getSearchProgramMasterBtnURL(searchObj);
3382		statusObj.api_type = 'master';
3383
3384		if(callback != null) parent[callback](result,load_status,searchObj,statusObj);
3385	});
3386
3387}
3388
3389/*--------------------------------------------------------------
3390	番組表マスターAPI:もっとみるボタンのURL
3391	2021/3/18
3392--------------------------------------------------------------*/
3393function getSearchProgramMasterBtnURL(searchObj){
3394	var query = (searchObj.query) ? "keyword="+searchObj.query : "";
3395	var genreId = (searchObj.genreId) ? "&genre="+searchObj.genreId : "";
3396	var queryTypeID = (searchObj.queryType) ? searchObj.queryType : "";
3397	var queryType = "";
3398	
3399	if(queryTypeID == 1){
3400		queryType = "&keywordType=or";
3401	}
3402	
3403	var targetChannels = "";
3404	var channel = "";
3405	
3406	//trace("searchObj.targetChannels "+searchObj.targetChannels);
3407	
3408	if(searchObj.targetChannels != null){
3409		targetChannels = getTargetChannelsQuery(searchObj.targetChannels);
3410	}else if(searchObj.serviceCode != null){
3411		channel = '&channel='+searchObj.serviceCode;
3412	}
3413	
3414	var keywordType = "";
3415	if(searchObj.queryType){
3416		keywordType = (searchObj.queryType == 0) ? "&keywordType=and" : "&keywordType=or";
3417	}
3418	
3419	var queryTarget = "";
3420	if(searchObj.queryTarget){
3421		if(searchObj.queryTarget == 1){
3422			queryTarget = '&keywordTarget=title';
3423		}else if(searchObj.queryTarget == 2){
3424			queryTarget = '&keywordTarget=detail';
3425		}
3426	}
3427	
3428	var url = "https://tvguide.myjcom.jp/search/event/?"+query+targetChannels+genreId+channel+keywordType+queryTarget;
3429	//if(isStage) url = "https://stage-tvguide.myjcom.jp/search/event/?"+query+targetChannels+genreId+channel+keywordType;
3430
3431	return encodeURI(url);
3432}
3433
3434/*--------------------------------------------------------------
3435	現在放送中 nowonair
3436--------------------------------------------------------------*/
3437var currentTimeForAPI_Date,currentTimeForAPI_Year,currentTimeForAPI_Month,currentTimeForAPI_Day,currentTimeForAPI_Hour,currentTimeForAPI_Minutes;
3438var currentTimestamp;
3439
3440function setCurrentTimeForAPI(){
3441	currentTimeForAPI_Date = new Date();
3442	//currentTimeForAPI_Date = new Date('2023-08-24 18:10:00');
3443
3444	currentTimeForAPI_Year = formatDate(currentTimeForAPI_Date, 'YYYY');
3445	currentTimeForAPI_Month = formatDate(currentTimeForAPI_Date, 'MM');
3446	currentTimeForAPI_Day = formatDate(currentTimeForAPI_Date, 'DD');
3447	currentTimeForAPI_Hour = parseInt(currentTimeForAPI_Date.getHours());
3448	currentTimeForAPI_Minutes = parseInt(currentTimeForAPI_Date.getMinutes());
3449
3450	var currentYear = currentTimeForAPI_Date.getFullYear();
3451	var currentMonth = ('0' + (currentTimeForAPI_Date.getMonth() + 1)).slice(-2);
3452	var currentDay = ('0' + currentTimeForAPI_Date.getDate()).slice(-2);
3453	var currentHour = ('0' + currentTimeForAPI_Date.getHours()).slice(-2);
3454	var currentMinute = ('0' + currentTimeForAPI_Date.getMinutes()).slice(-2);
3455	var currentSecond = ('0' + currentTimeForAPI_Date.getSeconds()).slice(-2);
3456	currentTimestamp = currentYear + currentMonth + currentDay + currentHour + currentMinute + currentSecond;
3457
3458}
3459
3460function checkThisProgramNowOnair(startDate,startTime,endTime){
3461		// NO ON AIR
3462		var flg_nowonair = false;
3463		var flg_todayonair = false;
3464
3465		// 指定した日時が本日中かどうかを判定する関数
3466		function isToday(datetime) {
3467			// var now = new Date();
3468			var currentDate = currentTimeForAPI_Date.getFullYear().toString() +
3469					('0' + (currentTimeForAPI_Date.getMonth() + 1)).slice(-2) +
3470					('0' + currentTimeForAPI_Date.getDate()).slice(-2);
3471
3472			var datePart = datetime.substring(0, 8);
3473			var datePartNumber = parseInt(datePart);
3474			return datePartNumber === parseInt(currentDate);
3475		}
3476
3477		// 開始日付と終了日付を数値に変換
3478		var startDate = parseInt(startTime.substring(0, 14));
3479		var endDate = parseInt(endTime.substring(0, 14));
3480		var currentTimestampNumber = parseInt(currentTimestamp);
3481
3482		// 現在の日付が開始日付と終了日付の間にあるか判定
3483		flg_nowonair = currentTimestampNumber >= startDate && currentTimestampNumber <= endDate;
3484
3485		// 開始日時と終了日時が本日中か判定
3486		flg_todayonair = isToday(startTime);
3487
3488		var onairTimeObj = {
3489			nowonair:flg_nowonair,
3490			todayonair:flg_todayonair
3491		}	
3492		
3493
3494		return onairTimeObj;
3495	
3496}//	

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.