PageSourceSearch

https://retty.me/javascripts/web_common.js

js retty.me collected 2026-09-24 08:51:31 UTC 101,528 bytes, 2,789 lines download raw bytes

1///////////////           テンプレート               ////////////////////////
2
3//ポップアップのテンプレート(OK/NO)
4function getPopUpTemplateA(id_prefix_arg){
5    var id_prefix = 'easy_popup';
6    if(id_prefix_arg) {
7	id_prefix = id_prefix_arg;
8    }
9    var a =
10"<table class='yn_popup'>"+
11    "<tr>"+
12        "<td id='" + id_prefix + "_message' colspan='2' val=''></td>"+
13    "</tr>"+
14    "<tr>"+
15        "<td id='" + id_prefix + "_okay'></td>"+
16        "<td id='" + id_prefix + "_cancel'></td>"+
17    "</tr>"+
18"</table>";
19    return a;
20}
21
22//ポップアップのテンプレート(FREE)
23function getPopUpTemplateB(){
24    var a =
25"<table class='free_popup'>"+
26    "<tr>"+
27        "<td id='easy_popup_area' val=''></td>"+
28    "</tr>"+
29"</table>";
30    return a;
31}
32
33//ポップアップのテンプレート(List)
34function getPopUpTemplateC(){
35	var a =
36"<table class='list_popup'>"+
37	"<tr>"+
38		"<td>"+
39			"<div id='easy_popup_discription' style='float:left;'></div>"+
40			"<div id='easy_popup_cancel' style='float:right;'><input type='button' value='閉じる'></div>"+
41		"</td>"+
42	"</tr>"+
43	"<tr>"+
44		"<td>"+
45			"<div id='easy_popup_list'></div>"+
46		"</td>"+
47	"</tr>"+
48"</table>";
49	return a;
50}
51
52///////////////           テンプレート               //////
52//////////////////
53
54/**
55 * APIからAJAXでデータを取得して、テンプレートに入れる
56 * apiUrl :
57 * param : set to 'p'
58 * selector : テンプレートから生成したHTMLを入れる要素のselector e.g. '#div1'
59 * expToEvalJson : APIから返ってきた結果→テンプレートに渡す値、の変換式。
60 *                 e.g. "{users: json}"
61 *                 空の場合は返ってきたJSONがそのままテンプレートに渡される
62 * callback : 描画後に実行される
63 */
64function loadApiData2Tmpl(apiUrl, param,
65                          selector, template,
66                          expToEvalJson, callback,cache) {
67    var data = new Object();
68    if(cache){
69        data = {"p":param ,"c":"true"};
70    }else{
71        data = {"p":param};
72    }
73    $.getJSON(apiUrl, data, function(json){
74        handleApiError(json);
75        if (!expToEvalJson) {
76            var data2tmpl = json;
77        } else {
78            eval("data2tmpl = " + expToEvalJson);
79        }
80        var html;
81        if (template.length > 20) {
82            // template がテンプレートの内容の場合
83            html = Mustache.to_html(template, data2tmpl);
84        } else {
85            // template がテンプレート名の場合
86            html = RtMustache.to_html(template, data2tmpl);
87        }
88        $(selector).append(html);
89        if (typeof callback == 'function') {
90            callback(json);
91        }
92    });
93}
94
95//エリアセレクトのポップアップ
96function AreaSelector (obj_name, id_place_holder) {
97  var phpscript = '/lib/area_select.php';
98  var self = this;
99  this.obj_name = obj_name; //TODO How to get this automatically?
100  this.id_place_holder = id_place_holder;
101  this.form_name = "as_form_area";
102
103  // element IDs
104  this.id_area_id = 'area_id'; // <input type=hidden> for lat
105  this.id_lat = 'lat'; // <input type=hidden> for lat
106  this.id_lng = 'lng'; // <input type=hidden> for lng
107  this.id_pref_selector = 'as_pref_selector';
108  this.id_area_selector = 'as_area_selector';
109  this.id_pref_selector_holder = "as_pref_selector_holder"; // Element for the select box for areas
110  this.id_area_selector_holder = "as_area_selector_holder"; // Element for the select box for areas
111  this.id_button = "as_select_button"; //
112  this.id_area_name = "as_area_name"; // Element that contains the area name
113  this.id_popup_area = "as_popup_area";
114  this.id_easy_popup = "easy_popup";
115
116  //variables
117  this.country_code = null;
118  this.pref_code = null;
119  this.area_id = null;
120  this.area_name = null;
121  this.lat = null;
122  this.lng = null;
123
124  this.popup_text = _('投稿したいエリアを選択してください');
125
126  this.init = function(pref_code, area_id, area_name, lat, lng) {
127    this.area_name = area_name;
128    if (pref_code) {
129      this.pref_code = pref_code;
130    } else {
131      this.pref_code = '13'; // 東京
132      if (!this.area_name) {
133        this.area_name = _('エリアを絞る');
134      }
135    }
136    this.area_id = area_id;
137    this.lat = lat;
138    this.lng = lng;
139
140    // register to ready;
141    // area selector
142    $(document).ready(function(){
143      $("#" + self.id_place_holder).html(self.html());
144      $("#" + self.id_lat).attr('value', self.lat);
145      $("#" + self.id_lng).attr('value', self.lng);
146      $("#" + self.id_button).hide();
147      $("#" + self.id_pref_selector_holder).load(phpscript, {mode: 'p', js_name: self.obj_name, id_pref_selector: self.id_pref_selector, prefecture: self.pref_code});
148      if (self.pref_code) {
149        self.load_area_selector(self.pref_code);
150      }
151    });
152  };
153
154    this.onSelectPrefecture = function(value) {
155        var ary = value.split(':');
156        this.country_code = ary[0];
157        this.pref_code = ary[1];
158        this.load_area_selector(self.pref_code);
159    };
160
161  this.load_area_selector = function(pref_code) {
162    $("#" + this.id_area_selector_holder).load(phpscript, {mode: 'a', prefecture: pref_code, id_area_selector: this.id_area_selector, area_id: this.area_id}, function(data) {
163	$("#" + self.id_button).show();
164    });
165  };
166
167  this.select_area = function () {
168    //var area_selector = form_area.area;//TODO
169    var selected_option = $('#' + this.id_area_selector + ' option:selected');
170    var area_selector = $('#' + this.id_area_selector);
171    var area = selected_option.attr('value');
172    var area_name = selected_option.html();
173    var area_info = area.split(",");
174    this.area_id = area_info[0];
175    this.area_name = area_name;
176    $("#" + this.id_area_name).html(area_name);
177    $("#" + this.id_area_id).attr('value', area_info[0]);
178    $("#" + this.id_lat).attr('value', area_info[1]);
179    $("#" + this.id_lng).attr('value', area_info[2]);
180//    alert(area_name + ":" + area_info[1] + ":" + area_info[2]);
181
182    if(this.onclick) {
183      this.onclick()
184    }
185
186    $("#" + this.id_easy_popup).trigger("click");
187  }
188
189  this.onclick = null;
190
191  this.popup = function() {
192    rtPopup('#' + this.id_popup_area, function() {$('#' + self.id_popup_area).hide();}, this.id_easy_popup);
193  }
194
195  this.html = function() {return '\
196	<strong>\
197		<a href="javascript:' + this.obj_name + '.popup();">\
198			<span id="'+ this.id_area_name +'">' + this.area_name + '</span>\
199		</a>\
200	</strong>\
201	<div style="display:none;">\
202		<div id="' + this.id_popup_area + '">\
203			<form name="' + this.form_name + '">\
204			<table class="restaurant_area_select">\
205				<tr>\
206			 		<td>\
207						<div class="center">\
208						' + this.popup_text + '\
209						</div>\
210						<div id="'+ this.id_pref_selector_holder +'" class="pref_selector"></div>\
211						<div id="'+ this.id_area_selector_holder +'" class="area_selector"></div>\
212						<div class="center">\
213							<input type="button" id="'+ this.id_button +'" class="buttonA" onclick="'+ this.obj_name +'.select_area();" value="' + _('決定') + '">\
214						</div>\
215					</td>\
216			 	</tr>\
217			</table>\
218			</form>\
219		</div>\
220	</div><!-- <div style="display:none;"> -->';
221  }
222
223}
224
225function AreaSelectorWithHistory(obj_name, id_place_holder, user_id
225) {
226  var that = new AreaSelector(obj_name, id_place_holder);
227
228	if(user_id != 0){
229        var url = "/API/OUT/slcuRecentUsedAreas/";
230        var data = {"p":user_id};
231        $.post(url, data, function(json){
232          that.areas = json;
233          that.insert_areas_html();
234        });
235	}
236
237  that.id_easy_popup = 'easy_popup_wide';
238  that.id_recent_areas = 'as_recent_areas';
239
240  that.insert_areas_html = function() {
241      var areas_html = '';
242      //that.areas[i].lat,lng
243      for (var i in that.areas) {
244	  var val = that.areas[i].prefecture_code + "," + that.areas[i].area_id + "," + that.areas[i].lat + "," + that.areas[i].lng;
245	  areas_html += '<li><a href="javascript:void(0)" onclick="' + that.obj_name + '.select_history(this)" val="' + val + '">' + that.areas[i].area_name + '</a></li>';
246      }
247      $("#" + that.id_recent_areas).html(areas_html);
248  }
249
250  that.select_history = function(elem) {
251    var area_name = $(elem).html();
252    var area_info = $(elem).attr('val').split(",");
253
254    var pref_id = area_info[0];
255    var area_id = area_info[1];
256    var lat = area_info[2];
257    var lng = area_info[3];
258    // $('#' + this.id_pref_selector).val(pref_id);
259    // $('#' + this.id_area_selector).val(area_id);
260    //console.log(pref_id + "," + area_id + "," + lat + "," + lng);
261
262    //
263    this.area_id = area_id;
264    $("#" + this.id_area_name).html(area_name);
265    $("#" + this.id_area_id).attr('value', area_id);
266    $("#" + this.id_lat).attr('value', lat);
267    $("#" + this.id_lng).attr('value', lng);
268
269    if(this.onclick) {
270      this.onclick()
271    }
272
273    $("#" + this.id_easy_popup).trigger("click");
274  };
275
276  that.select_area_cancel = function () {
277		$("#" + that.id_area_name).text("エリアで絞る");
278		$("#" + that.id_area_id).attr("value","");
279		this.area_id = "";
280    if(that.onclick) {
281      that.onclick()
282    }
283
284    $("#" + that.id_easy_popup).trigger("click");
285	};
286
287  that.html = function() {
288      return '\
289	<strong>\
290		<a href="javascript:' + this.obj_name + '.popup();">\
291			<span id="'+ this.id_area_name +'">' + this.area_name + '</span>\
292		</a>\
293	</strong>\
294	<div style="display:none;">\
295		<div id="' + this.id_popup_area + '" class="area_pref_selector">\
296			<table>\
297				<tr>\
298					<td>\
299					<img src="' + '/images/area_pref_selector/title02.png' + '" alt="' + _('前に行ったエリアから選択') + '" title="' + _('前に行ったエリアから選択') + '" />\
300						<ul id="' + this.id_recent_areas + '"></ul>\
301					</td>\
302					<td>\
303    					<img src="' + '/images/area_pref_selector/title01.png' + '" alt="' +_('詳しく探して選択') + '" title="' + _('詳しく探して選択') + '" />\
304						<form name="' + this.form_name + '">\
305							<div id="'+ this.id_pref_selector_holder +'" class="pref_selector"></div>\
306							<div id="'+ this.id_area_selector_holder +'" class="area_selector"></div>\
307							<div class="area_selector_button"><input type="button" id="'+ this.id_button +'" onclick="'+ this.obj_name +'.select_area();" value="' + _('決 定') + '"></div>\
308						</form>\
309                    <div id="place_cancel"><a href="javascript:void(0);"id="place_cancel_anker" onclick="'+ this.obj_name +'.select_area_cancel();">解除する</a></div>\
310					</td>\
311				</tr>\
312			</table>\
313		</div>\
314	</div><!-- <div style="display:none;"> -->';}
315  return that;
316}
317
318//スコアに応じてアイコン表示
319function displayScoreIcon(i, score_type, show_score3, resize) {
320    switch (score_type) {
321        case "1":
322            $("#score_type_" + i).html("<img src='" + "/images/score_1.png" + "' />");
323            break;
324        case "2":
325            $("#score_type_" + i).html("<img src='" + "/images/score_2.png" + "' />");
326            break;
327        case "3":
328            if (show_score3) {
329                $("#score_type_" + i).html("<img src='" + "/images/score_3.png" + "' />");
330            } else {
331                $("#score_type_" + i).html("<span class='score_display_none'></span>");
332                $("#report_comment_html_" + i).css('text-indent', '0px');
333                $("#report_comment_short_" + i).css('text-indent', '0px');
334                $("#report_comment_long_" + i).css('text-indent', '0px');
335            }
336            break;
337        case "4":
338            $("#score_type_" + i).html("<img src='" + "/images/score_4.png" + "' />");
339            break;
340    }
341    //通常は33px 44px
342    if (resize) {
343        $("#score_type_" + i).children("img").css("width", "25px");
344        $("#score_type_" + i).children("img").css("height", "33px");
345    }
346}
347
348//スコアに応じてアイコン表示
349//this function includes best icon
350function displayScoreIconWithBest(i,score_type, yearly_best_info) {
351    var yearly_best_info = yearly_best_info === undefined ? {} : yearly_best_info;
352	switch (true){
353        case 'year' in yearly_best_info:
354			$("#score_type_" + i).html("<img src='" + "/images/score_v2/ic_best_md_" + yearly_best_info.year + ".png" + "' width='90' height='18' />");
355            break;
356        case score_type == "1":
357			$("#score_type_" + i).html("<img src='" + "/images/score_v2/ic_score_md_excellent.png" + "' width='90' height='18' />");
358			break;
359        case score_type == "2":
360			$("#score_type_" + i).html("<img src='" + "/images/score_v2/ic_score_md_good.png" + "' width='60' height='18' />");
361			break;
362        case score_type == "3":
363			$("#score_type_" + i).html("<img src='" + "/images/score_v2/ic_score_md_average.png" + "' width='60' height='18' />");
364			break;
365        case score_type == "4":
366            // not to display score_4.png
367			break;
368	}
369}
370
371//スコアに応じてアイコン表示
372function displaySceneIcon(i,scene_type){
373	switch (scene_type){
374		case "1": //ランチ
375			$("#report_time_" + i).append("<img class='scene_icon' src='" + "/images/home/ic_sun.png" + "' />");
376			break;
377		case "2": //ディナー
378			$("#report_time_" + i).append("<img class='scene_icon' src='" + "/images/home/ic_moon.png" + "' />");
379			break;
380		case "3": //モーニング
381			$("#report_time_" + i).append("<img class='scene_icon' src='" + "/images/home/ic_morning.png" + "' />");
382			break;
383		case "4": //その他
384			$("#report_time_" + i).append("<img class='scene_icon' src='" + "/images/home/ic_other.png" + "' />");
385			break;
386        }
387        $("#report_time_" + i).children("img").css("width","15px");
388        $("#report_time_" + i).children("img").css("height","15px");
389}
390
391//いいねがある場合表示
392function displayRs1(i,sUserId,reply_score_1_user){
393        var rs1_list = "";
394        for ( ii in reply_score_1_user ){
395            var hash = reply_score_1_user[ii];
396            var uid = hash.reply_score_1_user_id;
397            var uname = hash.reply_score_1_user_name;
398            var uicon = hash.reply_score_1_user_icon;
399            var rs1_col = "<a href='/user/" + uid + "/'><img src='" + uicon + "' width='50' title='" + uname + "'/></a>";
400            var rs1_list = rs1_list + rs1_col;
401            if ( uid == sUserId ) {
402                    $("#rs1_image_" + i).hide();
403                    $("#rs1_delete_" + i).show();
404            }
405        }
406        return rs1_list;
407}
408
409//いきたいがある場合表示
410function displayRs2(i,sUserId,reply_score_2_user){
411        var rs2_list = "";
412        for ( ii in reply_score_2_user ){
413            var hash = reply_score_2_user[ii];
414            var uid = hash.reply_score_2_user_id;
415            var uname = hash.reply_score_2_user_name;
416            var uicon = hash.reply_score_2_user_icon;
417            var rs2_col = "<a href='/user/" + uid + "/'><img src='" + uicon + "' width='50' title='" + uname + "'/></a>";
418            var rs2_list = rs2_list + rs2_col;
419            if ( uid == sUserId ) {
420                    $("#rs2_image_" + i).hide();
421                    $("#rs2_delete_" + i).show();
422            }
423        }
424        return rs2_list;
425}
426
427/**
428 *  投稿に対するコメント、最後の2件以外は折りたたむ。
429 */
430function foldReplyComments(i, max_reply_comment_count){
431    $('#reply_comment_rows_' + i).children().each(
432        function(i, v) {
433            if (i < max_reply_comment_count - 2) {
434                $(this).hide();
435            }
436        });
437}
438
439/**
440 * コメントの「削除」ボタンにイベントを設定
441 */
442function clickAllReplyCommentDelete(sUserId, reply_comment){
443        for( var ii in reply_comment){
444                if ( isNaN(ii) ){break;}
445                var hash = reply_comment[ii];
446                var rc_id = hash.restaurant_comment_id;
447
448                //リプライコメント削除イベント
449                clickReplyCommentDelete(sUserId,rc_id);
450        }
451}
452
453//レポ削除イベント
454function popupReportDelete(i,sUserId){
455	$("#report_delete_" + i)
456		.click(function(){
457			id = $(this).attr("id").replace("report_delete_","");
458			var rname = $(this).attr("val");
459
460			var selec = "report_delete_notice_" +id;
461			popup(selec);
462			var a = getPopUpTemplateA();
463			$("#easy_popup_content")
464				.attr("class","popup_fixed")
465				.exFixed();
466			$("#easy_popup_inner")
467				.attr("style","width:100%;height:100%;overflow:auto;padding-top:95px;")
468				.append(a);
469			$("#easy_popup_message").append(_("<strong>%1</strong>の投稿を本当に削除しますか?", [rname]));
470			$("#easy_popup_okay").append("<input class='buttonA' type='button' size='50' id='report_delete_done_" + id + "' value='" + _('削除する') + "' />");
471			$("#easy_popup_cancel").append("<input class='buttonA' type='button' id='report_delete_quit_" + id + "' value='" + _('キャンセル') + "' />");
472
473			//YES
474			$("#report_delete_done_" + id).click(function(){
475				//表示を削除
476				$("#easy_popup").remove();
477				$("#easy_popup_inner").remove();
478				$("#easy_popup_content").remove();
479				$("#report_" + id).slideUp("slow");
480				//DBから削除
481				report_id = id;
482				upduReportStatus(sUserId,report_id,site_url);
483
484			});
485
486			//NO
487			$("#report_delete_quit_" + id).click(function(){
488				id = $(this).attr("id").replace("report_delete_done_","");
489				$("#easy_popup")
490					.remove()
491					.hide();
492				$("#easy_popup_content").hide();
493			});
494		});
495}
496
497var ReportImagePopup = new function () {
498    this._reportId = 0;
499    this._current = 1;
500    this._numOfImages = 0;
501    var self = this;
502
503    this.init = function(reportId) {
504        this._reportId = reportId;
505        this._numOfImages = $('#images_' + this._reportId).children().size();
506    };
507
508    this.setupEvent = function(reportId) {
509        $("#image_id_" + reportId).click(function() {
510            var reportId = $(this).attr('data-report-id');
511            self.init(reportId);
512            self.show();
513        });
514    };
515
516    this.show = function(_num) {
517        if (!self._numOfImages) {
518            return;
519        }
520
521        var num = _num ? _num : 1;
522        self._current = num;
523
524        self._showPopup();
525        self._showImage(num);
526        self._setupImagePager();
527        self._changeButtonsVisibility();
528    };
529
530    this._showPopup = function () {
531        var html = Mustache.to_html(TEMPLATES['popup_image'], []);
532        var node = $(html);
533        var popup = new Popup(node);
534        popup.show();
535        if (self._numOfImages <= 1) {
536            $('#popup_image_control').hide();
537        }
538    };
539
540    this._showImage = function (num) {
541	var large = $('#images_' + self._reportId + ' :nth-child(' + num + ')');
542        $("#image_loading").attr("src", '/images/loading_middle_bk.gif');
543        $("#image_loading").attr("src", large.attr('data-src'));
544    };
545
546    this._changeButtonsVisibility = function() {
547        if (self._current == 1) {
548            $('#popup_image_prev').css('visibility', 'hidden');
549        } else {
550            $('#popup_image_prev').css('visibility', 'visible');
551        }
552        if (self._current == self._numOfImages) {
553            $('#popup_image_next').css('visibility', 'hidden');
554        } else {
555            $('#popup_image_next').css('visibility', 'visible');
556        }
557    };
558
559    this._setupImagePager = function () {
560        $('#popup_image_prev').click(function(){
561            if (self._current > 1) {
562                self._current --;
563	        self._showImage(self._current);
564                self._changeButtonsVisibility();
565            }
566        });
567        $('#popup_image_next').click(function(){
568            if (self._current < self._numOfImages) {
569                self._current ++;
570	        self._showImage(self._current);
571                self._changeButtonsVisibility();
572            }
573        });
574    };
575};
576
577//写真拡大表示のイベント設定
578function popupReportImage(i){
579    ReportImagePopup.setupEvent(i);
580}
581
582//コメント全文表示イベント
583function showCommentLong(i){
584    $("#report_continue_" + i).click(function(){
585        id = $(this).attr("id").replace("report_continue_", "");
586        $('#report_comment_short_' + id).hide();
587        $(this).hide();
588        $('#report_comment_long_' + id).css('max-height', 'initial');
589        $('#report_comment_long_' + id).slideDown("fast");
590    })
591}
592
593
594//コメント全文表示解除イベント
595function hideCommentLong(i){
596	$("#report_close_" + i).click(function(){
597		id = $(this).attr("id").replace("report_close_", "");
598		$('#report_comment_long_' + id).hide();
599		$(this).hide();
600		$('#report_comment_short_' + id).show("slow");
601		$("#report_continue_" + id).show("slow");
602	})
603}
604
605//いいね!表示イベント
606function showReplyScore1(i,rs1_list){
607	$("#rs1_count_" + i).click(function(){
608		id = $(this).attr("id").replace("rs1_count_","");
609		popup("rs1_list_" + id);
610		var a = getPopUpTemplateC();
611		$("#easy_popup_content")
612			.attr("class","popup_fixed")
613			.exFixed();
614		$("#easy_popup_inner")
615			.attr("style","width:100%;height:100%;overflow:auto;")
616			.append(a);
617		$("#easy_popup_discription").append(_("いいね!と言っている人"));
618		$("#easy_popup_list").append(rs1_list);
619
620		//cancel
621		$("#easy_popup_cancel").click(function(){
622			$("#easy_popup")
623				.remove()
624				.hide();
625			$("#easy_popup_content").hide();
626		});
627	});
628	$("#rs1_count_" + i).css('cursor', 'pointer');
629}
630
631//いいね!入力イベント
632function clickReplyScore1(i, sUserId, sUserIcon, sUserName){
633	$("#rs1_image_" + i)
634		.mouseover(function(){
635			$(this).attr("src","/images/like_button_on.png");
636		})
637		.mouseleave(function(){
638			$(this).attr("src","/images/like_button_off.png");
639		})
640		.bind("click", function(){
641			id = $(this).attr("id").replace("rs1_image_", "");
642
643			//吹出し出現イベント
644			var brawser = $("html").attr("class");
645				if( brawser == "ch" || brawser == "fx" || brawser == "sa" || brawser == "op" ){
646					$("#rs1_popup_" + id).show();
647                                        setTimeout(function(){
648                                           $("#rs1_popup_" + id).fadeOut(1000);
649                                        },500);
650				}
651
652			//ボタンを変更
653			$("#rs1_image_" + id).hide();
654			$("#rs1_delete_" + id).show();
655
656			//詳細画面の表示を追加
657                        $("#rest_repo_no_friend").append("<img class='rounded-img2' height='50' width='50' title='"+sUserName+"' src='"+sUserIcon+"'>")
658
659			//いいね!カウントアップ
660			counter = $("#rs1_count_" + id).text();
661			var num = Number(counter);
662			var next_num = num + 1;
663			$("#rs1_count_" + id).text(next_num);
664
665			//いいね!DB入力
666			var report_id = id;
667			var user_id = $("#report_" + id).attr("val");
668			var reply_score_user_id = sUserId;
669			if (user_id == reply_score_user_id) {read_flag = 2;}
670			else {read_flag = 1;}
671
672			insuReplyScore1(reply_score_user_id,report_id,user_id,site_url);
673		});
674}
675
676//いいね削除イベント
677function clickReplyScoreDelete1(i,sUserId){
678	$("#rs1_delete_" + i)
679		.click(function(){
680			id = $(this).attr("id").replace("rs1_delete_", "");
681
682			//ボタンを変更
683			$("#rs1_delete_" + id).hide();
684			$("#rs1_image_" + id).show();
685
686			//詳細画面の表示を削除
687			$("#rs1_row_" + sUserId).hide();
688
689			//カウントダウン
690			counter = $("#rs1_count_" + id).text();
691			var num = Number(counter);
692			var before_num = num - 1;
693			$("#rs1_count_" + id).text(before_num);
694
695			//DBから削除
696			var report_id = id;
697			var reply_score_user_id = sUserId;
698			deluReplyScore1(reply_score_user_id,report_id,site_url);
699		});
700}
701
702//いきたい!表示イベント
703function showReplyScore2(i,rs2_list){
704	$("#rs2_count_" + i).click(function(){
705		id = $(this).attr("id").replace("rs2_count_","");
706		popup("rs2_list_" + id);
707		var a = getPopUpTemplateC();
708		$("#easy_popup_content")
709			.attr("class","popup_fixed")
710			.exFixed();
711		$("#easy_popup_inner")
712			.attr("style","width:100%;height:100%;overflow:auto;")
713			.append(a);
714		$("#easy_popup_discription").append(_("行きたいと言っている人"));
715		$("#easy_popup_list").append(rs2_list);
716
717		//cancel
718		$("#easy_popup_cancel").click(function(){
719			$("#easy_popup")
720				.remove()
721				.hide();
722			$("#easy_popup_content").hide();
723		});
724	});
725	$("#rs2_count_" + i).css('cursor', 'pointer');
726}
727
728//いきたい!入力イベント
729function clickReplyScore2(i, sUserId, sUserIcon, sUserName){
730	$("#rs2_image_" + i)
731		.mouseover(function(){
732			$(this).attr("src","/images/love_button_on.png");
733		})
734		.mouseleave(function(){
735			$(this).attr("src","/images/love_button_off.png");
736		})
737		.one("click", function(){
738			id = $(this).attr("id").replace("rs2_image_", "");
739
740			//吹出し出現イベント
741			var brawser = $("html").attr("class");
742				if( brawser == "ch" || brawser == "fx" || brawser == "sa" || brawser == "op" ){
743					$("#rs2_popup_" + id).show();
744                                         setTimeout(function(){
745                                           $("#rs2_popup_" + id).fadeOut(1000);
746                                        },500);
747				}
748
749			//ボタンを変更
750			$("#rs2_image_" + id).hide();
751			$("#rs2_delete_" + id).show();
752
753			//詳細画面の表示を追加
754                        $("#rest_rs2_no_friend").append("<img class='rounded-img2' height='50' width='50' title='"+sUserName+"' src='"+sUserIcon+"'>");
755
756			//いきたい!カウントアップ
757			counter = $("#rs2_count_" + id).text();
758			var num = Number(counter);
759			var next_num = num + 1;
760			$("#rs2_count_" + id).text(next_num);
761
762			//サイドバーのカウントアップ
763			var side_counter = $("#side_counter").text();
764			var side_num = Number(side_counter);
765			var side_next_num = side_num + 1;
766			$("#side_counter").text(side_next_num);
767
768			//いいね!DB入力
769			var report_id = id;
770			var user_id = $("#report_" + id).attr("val");
771			var reply_score_user_id = sUserId;
772			if (user_id == reply_score_user_id) {read_flag = 2;}
773			else {read_flag = 1;}
774			var user_name = sUserName;
775			var user_icon = sUserIcon;
776
777			insuReplyScore2(reply_score_user_id,report_id,user_id,site_url);
778
779                        //行きたいSNSポスト可否取得
780                        if( report_id != "3432"){
781                            slcWannagoPostFlag(reply_score_user_id,report_id);
782                        }
783
784                        // sessionStorage['wannago'] (サイドバーの「行きたい」エリア一覧?)を削除
785                        if (typeof(sessionStorage) != 'undefined') {
786                            sessionStorage.removeItem("wannago");
787                        }
788
789		});
790}
791
792//行きたいSNSポスト可否取得
793function slcWannagoPostFlag(reply_score_user_id,report_id){
794    var param = reply_score_user_id;
795    var data = {"p":param};
796    $.getJSON("/API/OUT/slcuWannagoPostFlag/", data, function(json){
797        var fbFlag = 0;
798        var twFlag = 0;
799        var initialPopupFlag = 0;
800        var attnetionPopupFlag = 0;
801        if (facebook_id && json.ufwp == 1) { //facebook null:未設定,1:ON,2:OFF,false:未連携
802            fbFlag = 1;
803        }
804        if (twitter_id && json.utwp == 1 ){ //twitter null:未設定,1:ON,2:OFF,false:未連携
805            twFlag = 1;
806        }
807        if( fbFlag || twFlag ){
808            function _doWannagoPost() {
809                //外部ポスト実行
810                var comment = "";
811                doWannagoPost(reply_score_user_id, report_id, fbFlag, twFlag, comment);
812                if( Math.floor(Math.random()*10) < 3 ){
813                    attnetionPopupFlag = 1;
814                }
815            }
816            if (fbFlag) {
817                var data = {'u': sUserId, 'p': sUserId};
818                    $.post('/F/u_canPostToFacebook/', data, function(canPost) {
819                        if (canPost) {
820                            _doWannagoPost();
821                        } else {
822                            showPopupNoFbPostPermission();
823                        }
824                    });
825            } else {
826                _doWannagoPost();
827            }
828        }
829        //初回ポップアップ表示
830        if( initialPopupFlag ){
831            var html =
832            "<div class='center'>"+
833                "<img src='" + "/images/popup/wannago_post_flag.png" + "' width='350' height='190' alt='" + _("新機能") + " " + _("あなたの「行きたい」がfacebook, twitterに投稿されるようになりました。") + _("「アカウント」から自由に設定できます。") + "' />"+
834            "</div>";
835            showPopupWannagoPost(html);
836        }
837        //アカウントで設定変更出来るアナウンスのポップアップ表示
838        $.getJSON("/F/checkWannagoPostAttentionFlag/", data, function(result){
839            if( result ){
840                attnetionPopupFlag = 0;
841            }
842            if( attnetionPopupFlag ){
843                var html =
844                "<div class='center'>"+
845                    "<img src='" + "/images/popup/wannago_post_flag02.png" + "' width='350' height='255' alt='" + _("FacebookやTwitterに共有したくない場合は画面右上の「設定変更」から設定が可能です。") + "' />"+
846                    "<div style='padding:8px;'><a href='javascript:void(0);' onclick='saveNotDisplayingWannagoPostPopup();' id='popup_connect_facebook_nomore'>×" + _('今後表示しない')+"</a></div>"+
847                "</div>";
848                showPopupWannagoPost(html);
849            }
850        });
851    });
852}
853
854//行きたいSNSポスト設定ポップアップ表示
855function showPopupWannagoPost(html){
856    popup("popup");
857    var a = getPopUpTemplateB();
858
859    $("#easy_popup_close").remove();
860    $("#easy_popup_content").attr("class","popup_fixed").exFixed();
861    $("#easy_popup_inner").attr("style","width:100%;height:100%;overflow:auto;").append(a);
862    $("#easy_popup_area").append(html);
863
864    $("#close_popup,#easy_popup_cancel").click(function(){
865        $("#easy_popup").remove().hide();
866        $("#easy_popup_content").hide();
867    });
868}
869
870//行きたいSNSポスト設定ポップアップを表示しない
871function saveNotDisplayingWannagoPostPopup(){
872    $("#easy_popup").remove();
873    $("#easy_popup_content").remove();
874    var data = {"u":sUserId, "p":sUserId};
875    $.post('/F/u_saveNotDisplayingWannagoPostAttention/', data );
876}
877
878//行きたいSNSポスト
879function doWannagoPost(reply_score_user_id, report_id, fbFlag, twFlag, comment, _callback,wannagoType){
880    var param = "";
881    if(wannagoType == undefined){
882        param = makeParam([reply_score_user_id, report_id, fbFlag, twFlag, comment]);
883    }else{
884        param = makeParam([reply_score_user_id, report_id, fbFlag, twFlag, comment ,wannagoType]);
885    }
886    var data = {"u":reply_score_user_id, "p":param};
887    var callback = _callback ? _callback : function(){};
888    $.post("/F/u_doWannagoPost/", data, callback);
889}
890
891//いきたい削除イベント
892function clickReplyScoreDelete2(i, sUserId){
893	$("#rs2_delete_" + i)
894		.click(function(){
895			id = $(this).attr("id").replace("rs2_delete_", "");
896
897			//ボタンを変更
898			$("#rs2_delete_" + id).hide();
899			$("#rs2_image_" + id).show();
900
901			//詳細画面の表示を削除
902			$("#rs2_row_" + sUserId).hide();
903
904			//カウントダウン
905			counter = $("#rs2_count_" + id).text();
906			var num = Number(counter);
907			var before_num = num - 1;
908			$("#rs2_count_" + id).text(before_num);
909
910			//サイドバーのカウントダウン
911			var side_counter = $("#side_counter").text();
912			var side_num = Number(side_counter);
913			var side_before_num = side_num - 1;
914			$("#side_counter").text(side_before_num);
915
916			//DBから削除
917			var report_id = id;
918			var reply_score_user_id = sUserId;
919			deluReplyScore2(reply_score_user_id,report_id,site_url);
920		});
921}
922
923//連れてって!表示イベント
924function showReplyScore3(i,rs3_list){
925	$("#rs3_count_" + i).click(function(){
926		id = $(this).attr("id").replace("rs3_count_","");
927		popup("rs3_list_" + id);
928		var a = getPopUpTemplateC();
929		$("#easy_popup_content")
930			.attr("class","popup_fixed")
931			.exFixed();
932		$("#easy_popup_inner")
933			.attr("style","width:100%;height:100%;overflow:auto;")
934			.append(a);
935		$("#easy_popup_discription").append(_("口説けると言っている人")); //camp8
936		$("#easy_popup_list").append(rs3_list);
937
938		//cancel
939		$("#easy_popup_cancel").click(function(){
940			$("#easy_popup")
941				.remove()
942				.hide();
943			$("#easy_popup_content").hide();
944		});
945	});
946}
947
948//リプライコメント全件表示イベント
949function showReplyComment(i){
950	$("#rc_display_" + i).toggle(function(){
951		id = $(this).attr("id").replace("rc_display_", "");
952		$(".rc_" + id).show();
953	}, function(){
954		$(".rc_" + id).hide();
955	});
956}
957
958//リプライコメント入力イベント
959function clickReplyComment(i, sid, sUserId, sUserIcon, sUserName, page){
960        page = page || 'false'; //home.phpのみ、リプライコメントの幅を変える
961
962        $("#comment_input_" + i)
963		.one("focus",function(){
964			id = $(this).attr("id").replace("comment_input_", "");
965			$(this).attr("value","").css({"color":"black"});
966			$("#comment_blank_" + id).animate({width: 0},350);
967                        if(page == 'home'){
968                            $("#comment_input_area_" + id).animate({width: 405},350);
969                            $("#comment_input_" + id).animate({width: 395},350);
970                        }else{
971                            $("#comment_input_area_" + id).animate({width: 520},350);
972                            $("#comment_input_" + id).animate({width: 512},350);
973                        }
974		})
975//		.focus(function(){
976//			$("#comment_blank_" + id).animate({ width: 130 },500);
977//			$("#comment_input_area_" + id).animate({ width: 315, height: 40 },500);
978//		})
979		.keypress(function(e){
980			var $$ = $(this);
981			if (e.which == 13) {
982				id = $(this).attr("id").replace("comment_input_", "");
983
984				var rc_value = $("#comment_input_" + id).attr("value");
985				rc_value = rc_value.replace(/[\n\r]/g,"");
986				if (rc_value == "") {
987					return false;
988				}else{
989
990					$(this).attr("value",_("コメントする")).hide().after("<img id='tmp_loading' src='" + "/images/loading_middle.gif" + "'/>");
991
992					//DBにINSERT
993					var report_id = id;
994					var user_id = $("#report_" + id).attr("val");
995					var reply_comment_user_id = sUserId;
996					var reply_comment = rc_value;
997					if (user_id == reply_comment_user_id) {
998						read_flag = 2;
999					}
1000					else {
1001						read_flag = 1;
1002					}
1003
1004					var url = "/API/IN/insuReplyComment/";
1005					var param = reply_comment_user_id+","+sid+","+report_id+","+user_id+","+escapeForCSV(reply_comment);
1006					var data = {"_source": getSource(), "p":param};
1007					$.post(url, data, function(json){
1008
1009						var url = "/API/OUT/slcLastReplyComment/";
1010						var data = {"p":sUserId};
1011						$.getJSON(url,data,function(json){
1012
1013							//コメントを表示する
1014							var user_name = sUserName;
1015							var user_icon = sUserIcon;
1016                                                        var last_comment_id = json.restaurant_comment_id;
1017							var last_comment = json.reply_comment;
1018							var last_datetime = json.create_datetime;
1019
1020							var data = {restaurant_comment_id: last_comment_id,
1021							            report_id: i,
1022							            rc_owner: true,
1023							            reply_comment_user_id: sUserId,
1024							            reply_comment_user_icon: sUserIcon,
1025							            reply_comment_user_name: sUserName,
1026							            reply_comment_create_datetime: '',
1027							            reply_comment: last_comment};
1028							var row = RtMustache.to_html('tl_comment', data);
1029
1030							$("#reply_comment_rows_" + id).append(row);
1031							$("#tmp_loading").remove();
1032							$("#comment_input_" + id).show().attr("value", "");
1033
1034							//コメント数カウントアップ
1035							counter = $("#reply_comment_count_" + id).text();
1036							var num = Number(counter);
1037							var next_num = num + 1;
1038							$("#reply_comment_count_" + id).text(next_num);
1039
1040                                                        //削除ボタン
1041                                                        clickReplyCommentDelete(sUserId, last_comment_id);
1042                                                        $("#reply_comment_delete_" + last_comment_id).text(_("削除"));
1043						});
1044						ga('send', 'event', 'Reviews', 'Comment', String(report_id));
1045					});
1046
1047				}
1048			}
1049		});
1050}
1051
1052//新着通知
1053var NotificationHandler = new function (){
1054    var self = this;
1055    //この/API/OUT/slcuNotifications/が呼び出された回数をwebのDAU計算に使っているのでAPIを変える場合はdevweb /home/retty/cron_devweb/cron_user_log.phpを修正すること
1056    var url = "/API/OUT/slcuNotifications/";
1057    var popup_selec = '#header_notifications';
1058    var count_selec = '#notifications_count';
1059
1060    var iconMap = {"1":{"name":"04","alt":_("フォロー")},
1061		   "2":{"name":"01","alt":_("いいね")},
1062		   "3":{"name":"02","alt":_("行きたい")},
1063		   "4":{"name":"03","alt":_("コメント")},
1064		   "5":{"name":"05","alt":_("行った")},
1065		   "6":{"name":"05","alt":_("フォロワーさんも行った")},
1066		   "7":{"name":"03","alt":_("口説けそう")},
1067		   "8":{"name":"_camp5","alt":_("投票")},
1068		   "9":{"name":"05","alt":_("始めました")},
1069		   "11":{"name":"03","alt":_("話題")},
1070		   "12":{"name":"03","alt":_("")},
1071		   "15":{"name":"03","alt":_("初めて投稿しました")},
1072		   "21":{"name":"03","alt": _("イベント招待")},
1073		   "22":{"name":"","alt":""},
1074		   "23":{"name":"03","alt": _("行きたいお店のイベントができました")}, /* TYPE_EVENT_WANNAGO_NOTIFICATION */
1075		   "24":{"name":"03","alt": _("フォローしているユーザーさんのイベントができました")}, /* TYPE_EVENT_FOLLOWER_NOTIFICATION */
1076		   "25":{"name":"03","alt":_("イベントメッセージ")},
1077		   "10":{"name":"05","alt":_("Rettyからのお知らせ")},
1078		   "28":{"name":"03","alt":_("ユーザーまとめからの投稿にいいね")},
1079		   "29":{"name":"03","alt":_("ユーザーまとめからの投稿に行きたい")},
1080		   "30":{"name":"03","alt":_("おまとめ通知")},
1081            //いいねとコメントはPCからのランディングページが無いので、現状は出さない
1082		    //"32":{"name":"03","alt":_("いいね")},
1083            //"33":{"name":"03","alt":_("コメント")},
1084		   "34":{"name":"03","alt":_("店舗情報修正通知")},
1085		   "37":{"name":"05","alt":_("ランキング")},
1086		   "38":{"name":"05","alt":_("行った")}
1087		   };
1088
1089    this.init = function(user_id) {
1090        var data = {"p":user_id + ",0,30"};
1091
1092	// Load the content here by using Ajax.
1093	$.getJSON(url, data, this.onsuccess);
1094
1095	// Event handler for click.
1096	$(count_selec).click(function() {
1097		var data_read = {"p":user_id};
1098		var url_read = "/API/IN/upduNotificationsAsRead/";
1099		if ($(count_selec).attr("class") != 'notifications_zero') {
1100			$.post(url_read, data_read);
1101		}
1102
1103		//新着表示を画面上から消す
1104		$(count_selec).attr("class", "notifications_zero");
1105		$(count_selec).text("");
1106
1107                ga('send', 'event', 'Notifications', 'Open');
1108	});
1109    };
1110
1111    var onClickLink = function(e) {
1112        var notificationType = $(this).attr('data-notification-type');
1113        ga('send', 'event', 'Notifications', 'Click', notificationType);
1114    };
1115
1116    this.getDataForTemplate = function (jsondata) {
1117        var data4tmpl = [];
1118        for(i in jsondata) {
1119            var row4tmpl = {};
1120            var row = jsondata[i];
1121
1122            var action_message = "";
1123            var action_type_icon = "";
1124            var action_type_icon_alt = "";
1125            var notification_type = row.notification_type;
1126
1127            //for https://github.com/natsukate/retty/issues/1047
1128
1129            row4tmpl['is_new'] = (row['status'] == 1);
1130            row4tmpl['create_datetime'] = row.create_datetime;
1131
1132            try{
1133                var data = $.parseJSON(row['notification_message']);
1134            } catch(e) {
1135                var data = "";
1136                console.log(e);
1137                continue;
1138            }
1139            var link = data['link'];
1140            if (link) { // check that data['link'] is existing
1141                if(link.match(/\?/)) {
1142                    link += '&_source=1';
1143                } else {
1144                    link += '?_source=1';
1145                }
1146            } else { // if link is not existing, go to next loop
1147                continue;
1148            }
1149
1150            row4tmpl['link'] = link;
1151            row4tmpl['action_user_name'] = data['action_user_name'];
1152            row4tmpl['action_user_icon'] = data['action_user_icon'] ? data['action_user_icon'] : '/images/logo-square.png';
1153
1154            var restaurant_name = data['restaurant_name'];
1155			var action_user_name = data['action_user_name'];
1156            var message = data['text_short'];
1157            if (!message) {
1158                message = data['text'];
1159            }
1160
1161            // アイコン、メッセージの設定。
1162            // メッセージは基本的にはサーバー側で生成されたものを使う。
1163            switch(notification_type){
1164            case "4": //コメント
1165                action_type_icon = "/images/header/notify_ico03.png";
1166                action_type_icon_alt = _("コメント");
1167                action_message = _("<strong>%1</strong>さんが<strong>%2</strong>の投稿にコメントしました", [action_user_name, restaurant_name]);
1168                break;
1169            case "25": //event_message 本来メッセージは別の新着だが、イベント時はここにも表示する
1170                action_type_icon = "/images/header/notify_ico03.png";
1171                action_type_icon_alt = _("イベントメッセージ");
1172                action_message = message;
1173                break;
1174            case "32": //ニュース記事へのいいね、コメントは表示しない
1175            case "33": //
1176			    continue;
1177            default:
1178                if (iconMap[notification_type]) {
1179		    if (iconMap[notification_type]["name"]) {
1180			action_type_icon = "/images/header/notify_ico" + iconMap[notification_type]["name"] + ".png";
1181                        action_type_icon_alt = iconMap[notification_type]["alt"];
1182			action_message = message;
1183		    } else {
1184			action_type_icon = "";
1185			action_message = message;
1186		    }
1187		} else {
1188		    continue;
1189		}
1190            }
1191            row4tmpl['action_type_icon'] = action_type_icon;
1192            row4tmpl['action_type_icon_alt'] = action_type_icon_alt;
1193            row4tmpl['action_message'] = action_message;
1194
1195            data4tmpl.push(row4tmpl);
1196	}
1197        return data4tmpl;
1198    };
1199
1200    this.onsuccess = function (jsondata) {
1201	if (isAPICallFailed(jsondata)) {
1202	    return;
1203	}
1204
1205        var data4tmpl = self.getDataForTemplate(jsondata);
1206
1207        var html = RtMustache.to_html('popup_notifications', data4tmpl);
1208	$(popup_selec).append(html);
1209        $('.notification_link').click(onClickLink);
1210    }; // onsuccess
1211
1212};
1213
1214// 改行コードを<br>タグに変換する
1215function convert_line_break(instr) {
1216  return instr.replace(/(\r\n|\r|\n)/g, '<br />');
1217}
1218
1219// レポート本文用のノード作成
1220function create_comment_node(text, id) {
1221	//console.log(text + ": <span>" + convert_line_break(text) + "</span>");
1222	var comment_node = $("<div class='review_comment'>" + convert_line_break(text) + "</div>");
1223	// brタグ以外を取り除く
1224	comment_node.contents().filter(function() {
1225//	    console.log(this.nodeType + "," + this.nodeName);
1226	    return this.nodeType == 1 && this.nodeName != "BR";
1227	}).remove();
1228
1229	// 生成されたノードが不正な場合、改行をすべて削除したバージョンを返す
1230	if (comment_node.size() != 1) {
1231		comment_node = $("<span></span>");
1232		comment_node.text(text);
1233	}
1234	comment_node.attr("id", id);
1235	comment_node.linkify({handleLinks: function (links){links.attr('target','_blank');}});
1236	return comment_node;
1237}
1238
1239//投稿関連イベント
1240function reportInputEvent(formSelector){
1241    var selectorPrefix = formSelector ? formSelector + ' ' : '';
1242
1243    //スコアクリック
1244    $(selectorPrefix + "#score1")
1245            .click(function(){
1246                    $("input[name=score]").attr('value',"1");
1247                    $("#score1_icon").attr("src","/images/contents/score_1_on.png");
1248                    $("#score2_icon").attr("src","/images/contents/score_2_off.png");
1249                    $("#score3_icon").attr("src","/images/contents/score_3_off.png");
1250                    $("#score4_icon").attr("src","/images/contents/score_4_off.png");
1251            });
1252    $(selectorPrefix + "#score2")
1253            .click(function(){
1254                    $("input[name=score]").attr('value',"2");
1255                    $("#score1_icon").attr("src","/images/contents/score_1_off.png");
1256                    $("#score2_icon").attr("src","/images/contents/score_2_on.png");
1257                    $("#score3_icon").attr("src","/images/contents/score_3_off.png");
1258                    $("#score4_icon").attr("src","/images/contents/score_4_off.png");
1259            });
1260    $(selectorPrefix + "#score3")
1261            .click(function(){
1262                    $("input[name=score]").attr('value',"3");
1263                    $("#score1_icon").attr("src","/images/contents/score_1_off.png");
1264                    $("#score2_icon").attr("src","/images/contents/score_2_off.png");
1265                    $("#score3_icon").attr("src","/images/contents/score_3_on.png");
1266                    $("#score4_icon").attr("src","/images/contents/score_4_off.png");
1267            });
1268    $(selectorPrefix + "#score4")
1269            .click(function(){
1270                    $("input[name=score]").attr('value',"4");
1271                    $("#score1_icon").attr("src","/images/contents/score_1_off.png");
1272                    $("#score2_icon").attr("src","/images/contents/score_2_off.png");
1273                    $("#score3_icon").attr("src","/images/contents/score_3_off.png");
1274                    $("#score4_icon").attr("src","/images/contents/score_4_on.png");
1275            });
1276
1277    //コメントカウントTODO
1278    $(selectorPrefix + "textarea[name=comment]").keyup(function(){
1279            var max = 500;
1280            var counter = $(this).val().length;
1281            var rest = max - counter;
1282            $("#counter").text(rest);
1283            if(rest < 0){
1284                    $("#counter").css("color","red");
1285                    $("#repo_submit_area").slideUp();
1286            }
1287            if(rest >= 0){
1288                $("#counter").css("color","");
1289                $("#repo_submit_area").slideDown();
1290            }
1291    });
1292
1293    $('#report_comment_form').rtReviewEditor();
1294
1295    //外部連携ボタン表示
1296    if( twitter_id != "" ){
1297        $(selectorPrefix + "#check_twitter").show();
1298        $(selectorPrefix + "input[name=twitter]").attr("value","ON");
1299    }
1300
1301    if( facebook_id != "" ){
1302        $(selectorPrefix + "#check_facebook").show();
1303        $(selectorPrefix + "input[name=facebook]").attr("value","ON");
1304    }
1305
1306    //送信ボタンクリック
1307    $(selectorPrefix + "#repo_submit")
1308            .mouseover(function(){
1309                    $(selectorPrefix + "#repo_submit img").attr("src","/images/contents/button_submit_on.png");
1310            })
1311            .mouseleave(function(){
1312                    $(selectorPrefix + "#repo_submit img").attr("src","/images/contents/button_submit_off.png");
1313            })
1314            .unbind("click")
1315            .click(function(){
1316                if ($(selectorPrefix + "input[name=facebook]").prop('checked')) {
1317                    var data = {'u': sUserId, 'p': sUserId};
1318                    $.post('/F/u_canPostToFacebook/', data, function(canPost) {
1319                        if (canPost) {
1320                            input_submit();
1321                        } else {
1322                            showPopupNoFbPostPermission();
1323                        }
1324                    });
1325                } else {
1326                    input_submit();
1327                }
1328            });
1329
1330    //閉じるイベント
1331    $('.close_area').click(function(){
1332        $('#exist_restaurant').slideUp();
1333    });
1334
1335}
1336
1337//レポ情報のDB登録
1338function insuUserRestaurantReport(user_id,sid,restaurant_id,report_comment,score_type,scene_type,favorite_type,site_url,
1339				  twitter_check, facebook_check, restaurant_name, org_report_id,draft_flg){
1340
1341        var status = 1;
1342        if(draft_flg == undefined){
1343            draft_flg = false;
1344        }else if(draft_flg == true){
1345            status = 4;
1346        }
1347	var imageIds = $('input[name="image_id[]"]').serialize();
1348	var imageKinds = $('select.image_kind').serialize();
1349	var param = user_id+","+sid+","+restaurant_id+","+escapeForCSV(report_comment)+","+score_type+","+scene_type+","+favorite_type+","+status+","+twitter_check+","+facebook_check+","+escapeForCSV(restaurant_name)+","+imageIds+","+draft_flg+","+imageKinds;
1350	var url;
1351        // 通常の投稿
1352        url = "/API/IN/insuUserRestaurantReport2/";
1353
1354        $('#exist_restaurant_loading').show(); //クルクルアイコン
1355
1356	var data = {"p":param};
1357	$.post(url,data,function(ret){
1358                $('#exist_restaurant_loading').hide(); //クルクルアイコン
1359		ga('send', 'event', 'Reviews', 'Post', String(ret['report']));
1360		var err = "";
1361                if (!ret["report"]) {
1362                    err += _("Rettyへの投稿に失敗しました。") + "\n" + _("何度も続くようでしたら、画面左の「Rettyへのご意見・ご感想」よりご連絡いただけますと幸いです。")
1363                }else{
1364                    if (!ret["facebook"]) {
1365                        err += _("Rettyへの投稿は完了しましたが、Facebookへ投稿できませんでした。") + "\n"
1366                            + ret["facebook_message"] + "\n";
1367                    } else if (ret["facebook"] != 'n/a') {
1368                            ga('send', 'event', 'Reviews', 'Post to Facebook', String(ret['report']));
1369                    }
1370                    if (!ret["twitter"]) {
1371                        err += _("Rettyへの投稿は完了しましたが、Twitterへ投稿できませんでした。") + "\n"
1372                            + ret["twitter_message"];
1373                    } else if (ret["twitter"] != 'n/a') {
1374                            ga('send', 'event', 'Reviews', 'Post to Twitter', String(ret['report']));
1375                    }
1376                    if (!ret["num_mentions"]) {
1377                            ga('send', 'event', 'Users', 'Mention', String(ret['report']), ret['num_mentions']);
1378                    }
1379                }
1380		if (err) {
1381		    alert(err);
1382		}
1383		all_done();
1384	});
1385}
1386
1387//投稿内容処理プロセス
1388function input_submit(){
1389
1390        $("#exist_restaurant").hide();
1391
1392	var restaurant_id = $("#restaurant_id").val();
1393        var report_comment = $("#report_comment_form").data('rtReviewEditor') ? $("#report_comment_form").rtReviewEditor('value') : $("#report_comment_form").val();
1394	var score_type = $("input[name=score]").val();
1395        var twitter_check = $("#report_done input[name=twitter]:checked").val();
1396	var facebook_check = $("#report_done input[name=facebook]:checked").val();
1397        var restaurant_name = $("#query_name").val();
1398	var scene_type = 0;
1399 	var favorite_type = 0;
1400
1401        if (typeof report_comment == 'undefined') {
1402            report_comment = '';
1403        }
1404
1405	//レポ情報の登録
1406	insuUserRestaurantReport(sUserId,sid,restaurant_id,report_comment,score_type,scene_type,favorite_type,site_url,
1407				 twitter_check, facebook_check, restaurant_name);
1408
1409	//カウントを増やす
1410	var itta_num = Number($("#side_repo_counter").text());
1411	itta_num++;
1412	$("#side_repo_counter").text(itta_num);
1413}
1414
1415function input_submit_draft(){
1416        $("#exist_restaurant").hide();
1417
1418	var restaurant_id = $("#restaurant_id").val();
1419        var report_comment = $("#report_comment_form").data('rtReviewEditor') ? $("#report_comment_form").rtReviewEditor('value') : $("#report_comment_form").val();
1420	var score_type = $("input[name=score]").val();
1421        var twitter_check = $("input[name=twitter]:checked").val();
1422	var facebook_check = $("input[name=facebook]:checked").val();
1423        var restaurant_name = $("#query_name").val();
1424	var scene_type = 0;
1425 	var favorite_type = 0;
1426 	var draft_flg = true;
1427
1428	//レポ情報の登録
1429	insuUserRestaurantReport(sUserId,sid,restaurant_id,report_comment,score_type,scene_type,favorite_type,site_url,
1430				 twitter_check, facebook_check, restaurant_name,false,draft_flg);
1431
1432	//カウントを増やす
1433	var itta_num = Number($("#side_repo_counter").text());
1434	itta_num++;
1435	$("#side_repo_counter").text(itta_num);
1436}
1437
1438//投稿終了時の諸処理
1439function all_done(){
1440
1441        var restaurant_id = $("#restaurant_id").val();
1442        var restaurant_name = $("#query_name").val();
1443	var facebook_check = $("input[name=facebook]:checked").val();
1444
1445	$("#report_comment_form").attr("value","");
1446        $("#query_name").attr("value","");
1447        $("#restaurant_id").attr("value","");
1448        $("#restaurant_name").attr("value","");
1449	// clearUploadedImage();
1450        FileUpload.cleanupAfterPosting(); // 1079. 問題ある
1451
1452	$('#last_restaurant').text(restaurant_name);
1453
1454	var browser_type = $("html").attr("class");
1455	if( browser_type == "fx" || browser_type == "ch" ){
1456		reloadTL();
1457	} else {
1458		reloadTL();
1459		//window.location="home.php";
1460	}
1461
1462        //localStorage['been']を削除
1463        if (typeof(sessionStorage) != 'undefined') {
1464            sessionStorage.removeItem("been");
1465        }
1466}
1467
1468//ログイン促しメッセージ
1469function alertLoginEvent(){
1470
1471    $(".rs_button").click(function(){
1472        dispInformation();
1473    });
1474
1475    $(".comment_input_form").focus(function(){
1476        dispInformation();
1477    });
1478
1479    $("#query_name").focus(function(){
1480        dispInformation();
1481    });
1482}
1483
1484function dispInformation(){
1485	popup("alert_login");
1486	var a = getPopUpTemplateB();
1487	var html = "<div id='notlogin_popup_users' class='notlogin_popup_users'><ul>"+
1488		"</ul></div>"+
1489		"<div class='notlogin_popup'>"+
1490		"<div id='easy_popup_cancel'><input type='button' value='" + _("閉じる") + "'></div>"+
1491		"<div class='popup_fb_login'><a href='/auth/facebook/?from=sidebar'><img id='facebook_login_button' alt='" + _("facebookアカウントで登録・ログイン") + "' src='" + "/images/notlogin/popup_fb_login_off.png" + "' alt='faceboook' onclick='ga(\"send\", \"event\", \"Guidance\", \"Click\", \"alert_login_facebook_click\");loginform_fb.submit();' width='365' height='55' /></a></div>"+
1492		"</div>";
1493
1494	// 人気ユーザーを表示
1495	var url = "/API/OUT/slcPopularUsers/";
1496	var data = {"p": "10"};
1497	$.getJSON(url, data, function(data){
1498            for (i in data) {
1499                var user = data[i];
1500                var li = $('<li><a href="" target="_blank"><img src="" width="40" height="40" alt="" title="" /></a></li>');
1501                var a = li.children('a');
1502                var img = a.children('img');
1503                a.attr('href', site_url + 'user/' + user.user_id + "/");
1504                img.attr('src', user.user_icon_file_name);
1505                img.attr('alt', user.user_name);
1506                img.attr('title', user.user_name);
1507                $("#notlogin_popup_users ul").prepend(li);
1508            }
1509	});
1510
1511	$("#easy_popup_close").remove();
1512	$("#easy_popup_content").attr("class","popup_fixed").exFixed();
1513	$("#easy_popup_inner").attr("style","width:100%;height:100%;overflow:auto;").append(a);
1514	$("#easy_popup_area").append(html);
1515	$("#close_popup,#easy_popup_cancel").click(function(){
1516            $("#easy_popup").remove().hide();
1517            $("#easy_popup_content").hide();
1518	});
1519        $(".popup_fb_login a")
1520            .mouseover(function(){
1521                $("img",this).attr("src","/images/notlogin/popup_fb_login_on.png");
1522            })
1523            .mouseleave(function(){
1524                $("img",this).attr("src","/images/notlogin/popup_fb_login_off.png");
1525	});
1526	clearTimeout();
1527
1528        ga('send', 'event', 'Guidance', 'View', 'alert_login');
1529}
1530
1531function GoogleMap(placeHolderId, lat, lng, option) {
1532    this._getLatLng = function(lat, lng) {
1533        var nLat = Number(lat);
1534        var nLng = Number(lng);
1535        return new google.maps.LatLng(nLat, nLng);
1536    }
1537
1538    this._myLatlng = this._getLatLng(lat, lng);
1539    this._myOptions = {
1540    	zoom: option.zoom != undefined ? option.zoom : 14,
1541        disableDefaultUI: option.disableDefaultUI!= undefined ? option.disableDefaultUI : true,
1542        mapTypeControl: option.mapTypeControl!= undefined ? option.mapTypeControl : true,
1543        navigationControl: option.navigationControl!= undefined ? option.navigationControl : false,
1544        center: this._myLatlng,
1545    	mapTypeId: option.mapTypeId!= undefined ? option.mapTypeId : google.maps.MapTypeId.ROADMAP
1546    };
1547    this._markers = [];
1548    this._bounds = new google.maps.LatLngBounds();
1549
1550    this.map = new google.maps.Map(document.getElementById(placeHolderId), this._myOptions);
1551
1552    this._getLatLng = function(lat, lng) {
1553        var nLat = Number(lat);
1554        var nLng = Number(lng);
1555        return new google.maps.LatLng(nLat, nLng);
1556    }
1557    this.setMarker = function(lat, lng, title, onclick) {
1558        var myLatlng = this._getLatLng(lat, lng);
1559
1560        var marker = new google.maps.Marker({
1561	                                        position: myLatlng,
1562	                                        map: this.map,
1563	                                        title: title
1564                                            });
1565        this._bounds.extend(myLatlng);
1566        this._markers.push(marker);
1567        if(typeof onclick == 'function') {
1568            google.maps.event.addListener(marker, 'click', onclick);
1569        }
1570        return marker;
1571    }
1572    this.setCenter = function(lat, lng) {
1573        var myLatlng = this._getLatLng(lat, lng);
1574        this.map.setCenter(myLatlng);
1575    }
1576    this.fitBounds = function() {
1577        this.map.fitBounds(this._bounds);
1578    }
1579    return this;
1580}
1581
1582/*
1583 * 新店舗登録画面で所在地の一部を入力すると自動補完してくれる機能
1584 * /mypage/regist-restaurant/から利用
1585 * need -> call jquery-ui.min.js
1586 * need -> call https://maps.google.com/maps/api/js?sensor=true&language=ja
1587 */
1588function setupAddressAutocompleteForRegistRestaurant(map, marker, address_textbox, onselectFunction) {
1589    var geocoder = new google.maps.Geocoder();
1590
1591    address_textbox.autocomplete({
1592		//This bit uses the geocoder to fetch address values
1593		source: function(request, response) {
1594            var countryCode = 'jp';
1595            var bounds = new google.maps.LatLngBounds();
1596            //余計なものが出ないように候補を日本の住所にしぼる
1597            //http://www.gsi.go.jp/KOKUJYOHO/center.htm
1598            //TODO いつかは海外対応
1599            var latlng1 = new google.maps.LatLng("20.2531","122.5601");
1600            var latlng2 = new google.maps.LatLng("45.332609","153.5911");
1601            bounds.extend(latlng1);
1602            bounds.extend(latlng2);
1603
1604			geocoder.geocode( {'address': request.term, 'region': countryCode, 'bounds' :bounds }, function(results, status) {
1605				response($.map(results, function(item) {
1606					item.formatted_address = item.formatted_address.replace((/^日本, /), '');
1607					return {
1608						label: item.formatted_address,
1609						value: item.formatted_address,
1610						latitude: item.geometry.location.lat(),
1611						longitude: item.geometry.location.lng(),
1612						address_components: item.address_components
1613					}
1614				}));
1615			});
1616		},
1617	    //This bit is executed upon selection of an address
1618	    select: function(event, ui) {
1619            var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
1620            map.setCenter(location);
1621            marker.setPosition(location);
1622
1623            var restaurant_info = _item2restaurantinfo(ui.item);
1624            onselectFunction(restaurant_info);
1625	    }
1626	});
1627}
1628
1629// Google APIから戻ってきた値を使いやすい形に加工
1630function _item2restaurantinfo(item) {
1631    var state = "";
1632    var city = "";
1633    var address = "";
1634    for (var i=item.address_components.length - 1; i >= 0; i--) {
1635        var component = item.address_components[i];
1636        if ($.inArray("country", component.types) != -1) {
1637            continue;
1638        } else if ($.inArray("administrative_area_level_1", component.types) != -1) {
1639            state = component.long_name;
1640        } else if ($.inArray("locality", component.types) != -1) {
1641            city = component.long_name;
1642        } else if ($.inArray("postal_code", component.types) == -1) { //postal_code以外
1643        if ($.inArray("sublocality_level_4", component.types) != -1) {
1644            address += '−';
1645        }
1646        address += component.long_name;
1647        }
1648    }
1649
1650    return {"state": state, "city": city, "address": address, "lat": item.latitude, "lng": item.longitude};
1651}
1652
1653// エラー処理関係ここから ------------
1654function isAPICallFailed(result) {
1655    return result['status'] == 'Failure';
1656}
1657
1658function handleApiError(result) {
1659    if(!isAPICallFailed(result)) {
1660        return; // エラーじゃなければ何もしない
1661    }
1662    if(result['statuscode'] == '403') {
1663        // Permission Denied
1664        alert(_("再度ログインを行って下さい。"));
1665        window.location = '/';
1666        return;
1667    }
1668    switch (result['exception']) {
1669    case 'Rt_Facebook_NotAuthorizedException':
1670        if (window.location.pathname != '/account.php') {
1671            alert(result['errormessage']);
1672            window.location = '/mypage/account-setting/';
1673        }
1674        return;
1675    default:
1676        return;
1677    }
1678}
1679// エラー処理関係ここから ------------
1680
1681function FormElement(idPrefix) {
1682    var self = this;
1683    this._idPrefix = idPrefix;
1684    this._options = {
1685        updateApi: '',
1686        userId: null,
1687        exp4updateParam: 'userId + "," + escapeForCSV(value)',
1688        onUpdateFinish: null, // 成功、失敗に関わらず呼ばれる
1689        onUpdateSuccess: null,
1690        onUpdateFailure: null,
1691        alwaysShowForm: true
1692    };
1693
1694    // publicメソッドの定義 ---------------------------
1695    this.setOptions = function(options) {
1696        for(key in options) {
1697            this.setOption(key, options[key]);
1698        }
1699    };
1700    this.setOption = function(key, val) {
1701        if(typeof this._options[key] == 'undefined') {
1702            throw "Invalid key '" + key + "'";
1703        }
1704        this._options[key] = val;
1705    };
1706    this.enable = function() {
1707        if(this._options['alwaysShowForm']) {
1708            this._showForm();
1709        }
1710        this._setupCommonEventHandlers();
1711        if(typeof this._setupEventHandlers == 'function') {
1712            this._setupEventHandlers();
1713        }
1714    };
1715    // ---- UI関連
1716    this.showSuccessMessage = function(message) {
1717        $('#' + self._idPrefix + '_message').show();
1718        $('#' + self._idPrefix + '_message').html(message);
1719        $('#' + self._idPrefix + '_message').fadeOut(5000);
1720    };
1721    this.showErrorMessage = function(message) {
1722        $('#' + self._idPrefix + '_message').show();
1723        $('#' + self._idPrefix + '_message').html(message);
1724    };
1725    this.disable = function() {
1726        self._hideForm();
1727        $('#' + self._idPrefix + '_edit').hide();
1728    };
1729    // 子クラス用のメソッドの定義 ----------------------
1730    this._getValue = function() {
1731        return $('#' + self._idPrefix + '_input').val();
1732    };
1733    this._getParam2Api = function() {
1734        var value = self._getValue();
1735        var userId = self._options['userId'] ? self._options['userId'] : sUserId;
1736        eval('var param = ' + self._options['exp4updateParam']);
1737        // console.log('param:' + param);
1738        if (this._options['updateApi'].match(/^\/F\/u_/)) {
1739            return {p: param, u: userId};
1740        } else {
1741            return {p: param};
1742        }
1743    };
1744    this._parseApiResult = function(apiResult) {
1745        var message = null;
1746        switch (typeof apiResult) {
1747        case 'string':
1748            var result = apiResult.length > 0;
1749            break;
1750        case 'boolean':
1751            var result = apiResult;
1752            break;
1753        case 'number':
1754            var result = apiResult;
1755            break;
1756        case 'object':
1757            var result = apiResult[0];
1758            message = apiResult[1];
1759            break;
1760        case 'undefined':
1761        case null:
1762            var result = false;
1763            break;
1764        }
1765        return {result: result, message: message};
1766    };
1767    // コールバックがセットされていれば呼び出す
1768    this._executeOnUpdateCallbacks = function(resultObj, apiResult) {
1769        if (typeof this._options['onUpdateFinish'] == 'function') {
1770            this._options['onUpdateFinish'](apiResult);
1771        }
1772        if (!resultObj['result']) {
1773            if (typeof this._options['onUpdateFailure'] == 'function') {
1774                this._options['onUpdateFailure'](apiResult);
1775            }
1776        } else {
1777            if (typeof this._options['onUpdateSuccess'] == 'function') {
1778                this._options['onUpdateSuccess'](apiResult);
1779            }
1780        }
1781    };
1782    this._setupCommonEventHandlers = function() {
1783        $('#' + this._idPrefix + '_edit').click(self._showForm);
1784        $('#' + this._idPrefix + '_quit').click(self._hideForm);
1785        $('#' + this._idPrefix + '_done').click(
1786            function() {
1787                var param = self._getParam2Api();
1788                // console.log(param);
1789                $.post(self._options['updateApi'], param, function(json) {
1790                           var apiResult = eval(json);
1791                           var resultObj = self._parseApiResult(apiResult);
1792                           self._onUpdateFinish(resultObj, apiResult);
1793                           self._executeOnUpdateCallbacks(resultObj, apiResult);
1794                       });
1795            });
1796    };
1797
1798    this._showForm = function() {
1799        $('#' + self._idPrefix + '_display').hide();
1800        $('#' + self._idPrefix + '_edit').hide();
1801        $('#' + self._idPrefix + '_input').show();
1802        $('#' + self._idPrefix + '_done').show();
1803        if(self._options['alwaysShowForm']) {
1804            $('#' + self._idPrefix + '_quit').hide();
1805        } else {
1806            $('#' + self._idPrefix + '_quit').show();
1807        }
1808    };
1809
1810    this._hideForm = function() {
1811        if(!self._options['alwaysShowForm']) {
1812            $('#' + self._idPrefix + '_display').show();
1813            $('#' + self._idPrefix + '_edit').show();
1814            $('#' + self._idPrefix + '_input').hide();
1815            $('#' + self._idPrefix + '_done').hide();
1816            $('#' + self._idPrefix + '_quit').hide();
1817        }
1818    };
1819
1820    // 子クラスで必要に応じてオーバーライドするメソッド ----------------------
1821    this._onUpdateFinish = function(resultObj, apiResult) {
1822        if (resultObj['result']) {
1823            var value = self._getValue();
1824            $('#' + self._idPrefix + '_display').html(value);
1825            self.showSuccessMessage(resultObj['message']);
1826            self._hideForm();
1827        } else {
1828            $('#' + self._idPrefix + '_message').show();
1829            self.showErrorMessage(resultObj['message']);
1830        }
1831    };
1832
1833}
1834
1835function FormElementText(idPrefix) {
1836    var that = new FormElement(idPrefix);
1837    var self = that;
1838
1839    return that;
1840}
1841
1842function FormElementRadio(idPrefix) {
1843    var that = new FormElement(idPrefix);
1844    var self = that;
1845    that._setupEventHandlers = function() {
1846    };
1847    that._getValue = function() {
1848        return $('input:radio[name="' + self._idPrefix + '_input"]:checked').val();
1849    };
1850    that._getLabel = function() {
1851        // console.log(that._getValue());
1852        return $('label[for="' + self._idPrefix + '_input-' + that._getValue() + '"]').text();
1853    };
1854    that._onUpdateFinish = function(resultObj, apiResult) {
1855        if (resultObj['result']) {
1856            var value = that._getLabel();
1857            $('#' + that._idPrefix + '_display').html(value);
1858            that.showSuccessMessage(resultObj['message']);
1859            that._hideForm();
1860        } else {
1861            $('#' + that._idPrefix + '_message').show();
1862            that.showErrorMessage(resultObj['message']);
1863        }
1864    };
1865    return that;
1866}
1867
1868function FormElementSelect(idPrefix) {
1869    var that = new FormElement(idPrefix);
1870    var self = that;
1871    that._getValue = function() {
1872        return $('select[name="' + self._idPrefix + '_input"] option:selected').val();
1873    };
1874    // that._getLabel = function() {
1875    //     // console.log(that._getValue());
1876    //     return $('label[for="' + self._idPrefix + '_input-' + that._getValue() + '"]').text();
1877    // }
1878    // that._onUpdateFinish = function(resultObj, apiResult) {
1879    //     if (resultObj['result']) {
1880    //         var value = that._getLabel();
1881    //         $('#' + that._idPrefix + '_display').html(value);
1882    //         that.showSuccessMessage(resultObj['message']);
1883    //         that._hideForm();
1884    //     } else {
1885    //         $('#' + that._idPrefix + '_message').show();
1886    //         that.showErrorMessage(resultObj['message']);
1887    //     }
1888    // }
1889    return that;
1890}
1891
1892function getFormElement(idPrefix, formType) {
1893    switch(formType.toLowerCase()) {
1894    case 'text':
1895        return new FormElementText(idPrefix);
1896    case 'textarea':
1897        // 処理はtextと同じ
1898        return new FormElementText(idPrefix);
1899    case 'select':
1900        return new FormElementSelect(idPrefix);
1901    case 'radio':
1902        return new FormElementRadio(idPrefix);
1903    default:
1904        //error
1905        return;
1906    }
1907    return null;
1908}
1909
1910function setEventHandlerForMenu(button_id, menu_id, options) {
1911    var duration = options && options['duration'] ? options['duration'] : 300;
1912    $('#' + button_id).hover(
1913
1914        function() {
1915	    $('#' + menu_id).slideDown(duration);
1916	}
1917    );
1918
1919
1920    // メニューからマウスが外れると、メニューを閉じる
1921    $(document).mouseover(function(event) {
1922	    if(!$(event.target).parents('#' + menu_id)[0] && event.target.id != button_id && event.target.id != menu_id) {
1923		$('#' + menu_id).slideUp(200);
1924	    }
1925	});
1926}
1927
1928var UserList = new function() {
1929    this.createHtml = function(users, template_name, prefix) {
1930	if (typeof prefix == 'undefined') {
1931	    prefix = '';
1932	}
1933
1934	var i = 0;
1935	for (key in users){
1936	    users[key]['even'] = (i % 2 == 0);
1937	    users[key]['odd'] = (i % 2 == 1);
1938	    i++;
1939	}
1940
1941	return RtMustache.to_html(template_name, {'users': users, 'prefix': prefix});
1942    };
1943};
1944
1945function Popup(elem, options) {
1946    var self = this;
1947
1948    if (elem instanceof jQuery) {
1949        this._elem = elem.clone().show();
1950    } else {
1951        this._elem = elem;
1952    }
1953    this._options = $.extend({
1954        'top': '15%',
1955        'left': '15%',
1956        'width': '70%',
1957        'height': '70%',
1958        'class': 'rt_popup',
1959        'class-inner': 'rt_popup_inner',
1960        'class-bg': 'rt_popup_bg',
1961        'color': '',
1962        'background': '',
1963        'destroy-on-close': true
1964    }, options);
1965
1966    this._id = "rt_popup";
1967    this._bgNodeId = "rt_popup_bg";
1968
1969    this._popupNode = null;
1970    this._popupInnerNode = null;
1971    this._bgNode = null;
1972
1973    this._init = function() {
1974        this._popupNode = $('<div id="' + this._id + '" class="' + this._options['class'] + '"></div>');
1975        this._popupInnerNode = $('<div id="' + this._id + '_inner" class="' + this._options['class-inner'] + '"></div>');
1976        this._bgNode = $('<div id="' + this._bgNodeId + '" class="' + this._options['class-bg'] + '"></div>');
1977        this._popupNode
1978	    .css("top", this._options['top'])
1979	    .css("left", this._options['left'])
1980	    .css("width", this._options['width'])
1981	    .css("height", this._options['height']);
1982        if (this._options['background']) {
1983            this._popupNode.css("background", this._options['background']);
1984            this._popupInnerNode.css("background", this._options['background']);
1985        }
1986        if (this._options['color']) {
1987            this._popupNode.css("color", this._options['color']);
1988            this._popupInnerNode.css("color", this._options['color']);
1989        }
1990        if (this._popupNode.exFixed) {
1991            this._popupNode.exFixed();
1992        }
1993        this._popupInnerNode
1994	    .css("width","100%")
1995	    .css("height","100%");
1996        this._popupInnerNode.append(this._elem);
1997        this._popupNode.append(this._popupInnerNode);
1998        $(document.body).append(this._bgNode);
1999        $(document.body).append(this._popupNode);
2000        // 一旦非表示に
2001        this._popupNode.hide();
2002        // this._bgNode.click(function() {self.hide();});
2003    };
2004    this._init();
2005
2006    this._showBg = function() {
2007        this._bgNode.css("top", 0);
2008        this._bgNode.css("left", 0);
2009        this._bgNode.css("height", $(document).height());
2010        this._bgNode.css("width", $(document).width());
2011        this._bgNode.show();
2012        if(this._options['destroy-on-close']) {
2013            this._bgNode.click(self.destroy);
2014        } else {
2015            this._bgNode.click(self.hide);
2016        }
2017    };
2018
2019    // -----------------
2020    this.show = function() {
2021        //既に別のポップアップが開いていれば
2022        if ($(document).data('rtpopup-open') || $('#easy_popup:visible').length) {
2023            $(document).one('rt-popup-hide', self.show);
2024        } else {
2025            self._show();
2026        }
2027    };
2028    this._show = function() {
2029        $(document).data('rtpopup-open', true);
2030        this._popupNode.show();
2031        this._showBg();
2032    };
2033
2034    this.hide = function() {
2035        self._popupNode.hide();
2036        self._bgNode.hide();
2037        $(document).data('rtpopup-open', false);
2038        $(document).trigger('rt-popup-hide');
2039    };
2040
2041    this.destroy = function () {
2042        self._popupNode.remove();
2043        self._bgNode.remove();
2044        $(document).data('rtpopup-open', false);
2045        $(document).trigger('rt-popup-hide');
2046    };
2047}
2048
2049/**
2050 * TL関係の処理
2051 */
2052var Tl = new function() {
2053    var self = this;
2054
2055    this.finishLoading = function() {
2056        // console.log('finish!!');
2057        $(document).trigger('rt-tl-finish-loading');
2058    };
2059
2060    /**
2061     * TL上の投稿のもっと読む、report_comment_html バージョン
2062     */
2063    this.setupShowLongCommentHtml = function () {
2064        $(".report_continue").live('click', function(){
2065            var id = $(this).attr("data-report-id");
2066            var $commentElem = $('#report_comment_html_' + id);
2067            var height = $commentElem.attr('data-content-height') + 'px';
2068            // console.log(id);
2069            // console.log($commentElem);
2070            $commentElem.animate({'max-height': height});
2071            $(this).hide();
2072        });
2073    };
2074
2075    /**
2076     * 「続きを見る」を表示する
2077     */
2078    this.showReadMoreForLongReview = function($comment, $continue, $image) {
2079        var imageWidth = $image.outerWidth(true);
2080        var blockWidth = $comment.actual('width');
2081
2082        $comment.wrapInner('<div />');
2083
2084        if($image && $image.length > 0) {
2085            $comment.children('div').width(blockWidth - imageWidth);
2086        }
2087
2088        var contentWidth = $comment.children('div').actual('width');
2089        var contentHeight = $comment.children('div').actual('height');
2090        $comment.css('max-width', contentWidth);
2091
2092        var blockHeight = $comment.actual('height');
2093        if (contentHeight <= blockHeight){
2094            $continue.hide();
2095        } else {
2096            $continue.show();
2097        }
2098
2099        $comment.children('div').replaceWith($comment.children('div').html());
2100        $comment.attr('data-content-height', contentHeight);
2101    };
2102
2103
2104};
2105
2106/**
2107 * マウスをあてるとポップアップがでてくるやつの設定
2108 */
2109function setupHoverPopup(options) {
2110    var selector = options['selector'];
2111    var url = options['url'];
2112    var param = options['param'];
2113    var content = options['content'];
2114    var gaLabel = options['ga-label'];
2115
2116    var position = options['position'] ? options['position'] : {my:'top left', at:'bottom left'};
2117    $(selector).live('mouseover', function(event) {
2118        var elem = $(this);
2119        var paramStr = null;
2120        if (typeof param == 'function') {
2121            paramStr = param(event);
2122        } else {
2123            paramStr = param;
2124        }
2125        if (!paramStr) {
2126            return;
2127        }
2128        elem.qtip({
2129            overwrite: false,
2130            content: {
2131                text: '<div class="center"><img src="/images/loading_middle.gif" /></div>',
2132                ajax: {
2133                    url: url,
2134                    type: 'GET',
2135                    data: {p:paramStr},
2136                    dataType: 'json',
2137                    success: function(data, status) {
2138                        var contentStr = null;
2139                        if (typeof content == 'function') {
2140                            contentStr = content(data, status);
2141                        } else {
2142                            contentStr = content;
2143                        }
2144                        if (contentStr) {
2145                            this.set('content.text', contentStr);
2146                        } else {
2147                            //TODO hide the element
2148                        }
2149                        if (gaLabel) {
2150                            ga('send', 'event', 'Popups', 'Open', gaLabel);
2151                        }
2152                    }
2153                }
2154            },
2155            position: position,
2156            show: {ready: true},
2157            hide: {fixed: true, delay: 200},
2158            delay: 200,
2159            style: {
2160                def: false,
2161                classes: 'rt_popup_qtip'
2162            }
2163        }, event);
2164    });
2165}
2166
2167function setupUserPopup(selector) {
2168    var popup = null;
2169    var paramFunc = function(event) {
2170        var elem = $(event.target);
2171        var targetUserId = elem.attr('data-user-id');
2172        if (!targetUserId || targetUserId == sUserId) {
2173            return false;
2174        }
2175
2176        // // 既にポップアップ上の場合、表示しない
2177        // if(elem.parents('.qtip')[0]) {
2178        //     return;
2179        // }
2180
2181        return makeParam([sUserId, targetUserId]);
2182    };
2183    var contentFunc = function(data, status) {
2184        return RtMustache.to_html('popup_user_small', data);
2185    };
2186    setupHoverPopup({selector: selector, url: '/API/OUT/slcuUserInfoWithRelations/',
2187                     param: paramFunc, content: contentFunc, 'ga-label': 'User',
2188                     position: {at:'bottom left', adjust: {x: 5}}});
2189
2190    $('.popup_user_small .following_button').live('click', function(e) {
2191        var elem = $(this);
2192        var targetUserId = elem.attr('data-user-id');
2193        clickFollowingMain(sUserId, targetUserId);
2194        elem.hide();
2195        elem.siblings('.unfollowing_button').show();
2196        ga('send', 'event', 'Popups', 'Follow', 'User');
2197    });
2198    $('.popup_user_small .unfollowing_button').live('click', function(e) {
2199        var elem = $(this);
2200        var targetUserId = elem.attr('data-user-id');
2201        deluFollowingMain(sUserId, targetUserId);
2202        elem.hide();
2203        elem.siblings('.following_button').show();
2204        ga('send', 'event', 'Popups', 'Unfollow', 'User');
2205    });
2206}
2207
2208function setupCommonIttaHover(selector) {
2209    setupHoverPopup({
2210        selector: selector, url: '/API/OUT/slcuCommonBeenRestaurants/',
2211        param: function(event) {
2212            var elem = $(event.target);
2213            var targetUserId = elem.attr('data-user-id');
2214            if (!targetUserId) {
2215                return false;
2216            }
2217            return makeParam([sUserId, following_user_id, targetUserId]);
2218        },
2219        content: function(data, status) {
2220            if (data) {
2221                return RtMustache.to_html('popup_common_been_restaurants', data);
2222            } else {
2223                return false;
2224            }
2225        }
2226    });
2227}
2228
2229function setupCommonIkitaiHover(selector) {
2230    setupHoverPopup({
2231        selector: selector, url: '/API/OUT/slcuCommonWannagoRestaurants/',
2232        param: function(event) {
2233            var elem = $(event.target);
2234            var targetUserId = elem.attr('data-user-id');
2235            if (!targetUserId) {
2236                return false;
2237            }
2238            return makeParam([sUserId, following_user_id, targetUserId]);
2239        },
2240        content: function(data, status) {
2241            if (data) {
2242                return RtMustache.to_html('popup_common_wannago_restaurants', data);
2243            } else {
2244                return false;
2245            }
2246        }
2247    });
2248}
2249
2250/**
2251 * $.rtReviewEditor
2252 */
2253(function($) {
2254    // contenteditable div でも val() が使えるように
2255    var fnValOrg = $.fn.val;
2256    $.fn.val = function() {
2257        var $this = $(this);
2258        if ($this.data('rtReviewEditor')) {
2259            return $this.rtReviewEditor('value', arguments);
2260        };
2261        return fnValOrg.apply(this, arguments);
2262    };
2263    // rangy.init();
2264    // var range = rangy.createRange();
2265
2266    var methods = {
2267        init: function(options) {
2268            var settings = $.extend({}, options);
2269            return this.each(function() {
2270                var $this = $(this);
2271                if (!$this.is('div')) {
2272                    $.error('rtReviewEditor is applicable only for divs');
2273                    return;
2274                }
2275                $this.attr('contenteditable', true);
2276                var initialVal = $this.text();
2277
2278                // data
2279                var data = $this.data('rtReviewEditor');
2280                if (!data) {
2281                    $this.data('rtReviewEditor', {
2282                        target: $this
2283                    });
2284                    data = $this.data('rtReviewEditor');
2285                }
2286
2287                $.getJSON('/API/OUT/slcuTags4AutoComplete/', {p: sUserId}, function(json) {
2288                    var data = $.map(json, function(val, key) {
2289                        return {value: val.tag_text, label: '#' + val.tag_text};;
2290                    });
2291                    _setData($this, 'tag-options', data);
2292                });
2293
2294                _setValue($this, initialVal);
2295                _render($this, initialVal);
2296
2297                $this.bind('keyup.rtReviewEditor blur.rtReviewEditor', _eventHandler);
2298                _setupAutoComplete($this, _sourceFunc);
2299            });
2300        },
2301
2302        /**
2303         * divの中身を parse して、内部状態を更新。
2304         */
2305        refresh: function() {
2306            return this.each(function() {
2307                var $this = $(this);
2308                var result = _parseDiv($this);
2309                // console.log(result);
2310                _setValue($this, result['text']);
2311            });
2312        },
2313
2314        /**
2315         * この「フォーム」の値を返す。
2316         */
2317        value: function(args) {
2318            if (args && args.length) {
2319                _setValue($(this), args[0]);
2320                _render($(this), args[0]);
2321                return $(this);
2322            } else {
2323                return $(this).attr('data-rtrevieweditor-value');
2324            }
2325        }
2326    };
2327    var chars = '[\\wぁ-んァ-ン一-龥朗-鶴]';
2328    var reMentionInternal = new RegExp('@\\[(\\d+):(.+?)\\]', 'g');
2329    var reMention = new RegExp('(@|ï¼ )(' + chars + '*)$');
2330    var reTag = new RegExp('(#|#)(' + chars + '*)$');
2331
2332    // private functions ------------------
2333    function _getData($this, key) {
2334        var data = $this.data('rtReviewEditor');
2335        return data[key];
2336    }
2337    function _setData($this, key, value) {
2338        var data = $this.data('rtReviewEditor');
2339        return data[key] = value;
2340    }
2341
2342    function _setupAutoComplete(elem, sourceFunc) {
2343        elem.keydown( function( event ) {
2344            var $this = $(this);
2345            var isOpen = $this.autocomplete( "widget" ).is( ":visible" );
2346            var keyCode = $.ui.keyCode;
2347            // console.log('keydown ' + isOpen + "," + event.keyCode);
2348            if ( !isOpen && ( event.keyCode == keyCode.UP || event.keyCode == keyCode.DOWN ) ) {
2349	        event.stopImmediatePropagation();
2350            }
2351            // autocompleteの選択肢が表示されている状態でESCを押したときは閉じる。
2352            if (isOpen && event.keyCode == keyCode.ESCAPE) {
2353                $this.autocomplete("close");
2354                // イベントの上位への伝搬を止めないと、カーソルが先頭に戻ってしまう。
2355                event.stopImmediatePropagation();
2356            }
2357        }).autocomplete({
2358            source: sourceFunc,
2359            focus: function() {
2360	        return false;
2361            },
2362            select: function(event, ui) {
2363                var $this = $(this);
2364                var startPos = _getData($this, 'startpos');
2365                var matched =  _getData($this, 'matched-mention');
2366                var html, nodeIndex, offset;
2367                if (matched) { // mention が選択された場合
2368                    var htmlBeforeMention = _convertToHtml($this.val().substr(0, startPos - matched[0].length));
2369                    var htmlAfterMention = _convertToHtml($this.val().substr(startPos));
2370                    // span を作成し、それを埋め込む
2371                    var mentionSpan = _createMentionSpan(ui.item.value, ui.item.label);
2372                    html = htmlBeforeMention + mentionSpan + '&nbsp;' + htmlAfterMention;
2373                    nodeIndex = Number(_getData($this, 'position-node-index')) + 1;
2374                    offset = 1;
2375                    _setData($this, 'matched-mention', null);
2376                }
2377
2378                matched = _getData($this, 'matched-tag');
2379                if (matched) { // tag が選択された場合
2380                    var htmlBeforeTag = _convertToHtml($this.val().substr(0, startPos - matched[0].length));
2381                    var htmlAfterTag = _convertToHtml($this.val().substr(startPos));
2382                    // タグのテキストをそのまま埋め込み
2383                    html = htmlBeforeTag + ui.item.label + '&nbsp;' + htmlAfterTag;
2384                    nodeIndex = Number(_getData($this, 'position-node-index'));
2385                    offset = Number(_getData($this, 'position-offset')) - matched[0].length + ui.item.label.length + 1;
2386                    _setData($this, 'matched-tag', null);
2387                }
2388
2389                $this.html(html);
2390                // var newpos = textBeforeMention.length + mentionSpan.length + 1;
2391                $this.focus(); // フォーカスを当てないとカーソルの位置を変えられない
2392                _setCursorPosition(this, nodeIndex, offset);
2393                $this.rtReviewEditor('refresh');
2394                return false;
2395            },
2396            position: {my : "left top", at: "left bottom"},
2397            open: function(){
2398                $(".ui-autocomplete:visible").css("z-index", "10020");
2399            }
2400        });
2401    }
2402
2403    function _sourceFunc(request, response) {
2404        // "this" is the widget?
2405        var mentionMatch = _extractToken(request.term, this, reMention);
2406        if(mentionMatch != null){
2407            // console.log('mention source: match');
2408            var mention = mentionMatch[2];
2409            _setData(this.element, 'matched-mention', mentionMatch);
2410            var mentionOptions = _getData(this.element, 'mention-options');
2411            var mentionOptionsToDisplay = $.ui.autocomplete.filter(mentionOptions, mention);
2412            response(mentionOptionsToDisplay.slice(0, 10)); // 10件に絞る
2413            return;
2414        }
2415        var tagMatch = _extractToken(request.term, this, reTag);
2416        if(tagMatch != null){
2417            // console.log('tag source: match');
2418            var tag = tagMatch[2];
2419            _setData(this.element, 'matched-tag', tagMatch);
2420            var tagOptions = _getData(this.element, 'tag-options');
2421            response($.ui.autocomplete.filter(tagOptions, tag));
2422            return;
2423        }
2424        response([]);
2425    }
2426
2427    /**
2428     * @param String str 文字列
2429     * @param Object area contenteditable divのノード
2430     * @param Object re 正規表現オブジェクト
2431     */
2432    function _extractToken(str, area, re) {
2433        var $this = area.element ? area.element : $(area);
2434        var start = _getCurrentPosition($this);
2435        _setData($this, 'startpos', start);
2436        // console.log(str.substring(0, start));
2437        return str.substring(0, start).match(re);
2438    }
2439
2440    /**
2441     * 現在のカーソル位置を取得する。
2442     * contenteditable divの場合、dataの中に以下の2つの値をセットする
2443     * 'position-node-index' カーソルがあるノードは、divの中の何番目のノードか
2444     * 'position-offset' そのノードの中での位置
2445     * @return integer data-rtrevieweditor-value のどこにカーソルがあるか
2446     */
2447    function _getCurrentPosition($this) {
2448        if($this.is('[contenteditable]')) {
2449            var sel = window.getSelection();
2450            var range = document.createRange();
2451            var count = 0;
2452            var stop = false;
2453            $this.contents().each(function(i, e) {
2454                if (e == sel.anchorNode) {
2455                    _setData($this, 'position-node-index', i);
2456                    _setData($this, 'position-offset', sel.anchorOffset);
2457                    stop = true;
2458                } else if (!stop) {
2459                    if (e.nodeType == 3) {  // text node
2460                        // console.log(e.textContent + "," + e.textContent.length + "," + e.nodeValue);
2461                        count += e.textContent.length;
2462                    } else {
2463                        $e = $(e);
2464                        if ($e.is('br')) {
2465                            count += 1;
2466                        } else if ($e.is('span[data-rtrevieweditor-mention]')) {
2467                            var userId = $e.attr('data-rtrevieweditor-mention');
2468                            var userName = $e.text();
2469                            var mention = '@[' + userId + ':' + escapeHtml(userName) + ']';
2470                            count += mention.length;
2471                        }
2472                    }
2473                }
2474            });
2475            return count + sel.anchorOffset;
2476        } else {
2477            return $this[0].selectionStart;
2478        }
2479    }
2480
2481    function _setCursorPosition(node, pos, offset) {
2482        var $this = $(node),
2483            range;
2484        if($this.is('[contenteditable]')) {
2485            range = document.createRange();
2486            var sel = window.getSelection();
2487            if (!node.childNodes[pos]) {
2488                return;
2489            }
2490            range.setStart(node.childNodes[pos], offset);
2491            range.collapse(true);
2492            sel.removeAllRanges();
2493            sel.addRange(range);
2494        } else {
2495	    if (node.setSelectionRange) {
2496	        node.setSelectionRange(pos, pos);
2497	    } else if (node.createTextRange) {
2498	        range = node.createTextRange();
2499	        range.collapse(true);
2500	        range.moveEnd('character', pos);
2501	        range.moveStart('character', pos);
2502	        range.select();
2503	    }
2504        }
2505    }
2506
2507    /**
2508     * Sets value to the plugin. The value may contain line breaks and html tags,
2509     * which will be encoded as "&lt;tag&gt;".
2510     */
2511    function _setValue(target, text) {
2512        target.attr('data-rtrevieweditor-value', text);
2513    }
2514
2515    /**
2516     * Renders the passed text as HTML for the div.
2517     */
2518    function _render(target, text) {
2519        // console.log(_convertMentions(escapeHtml(text)));
2520        target.html(_convertToHtml(text));
2521    }
2522
2523    /**
2524     * Converts text containing internal representations of mentions to HTML
2525     */
2526    function _convertToHtml(text) {
2527        return convert_line_break(_convertMentions(escapeHtml(text)));
2528    }
2529
2530    function _convertMentions(text) {
2531        return text.replace(reMentionInternal, function(match, $1, $2, offset, s) {
2532            return _createMentionSpan($1, $2);
2533        });
2534    }
2535
2536    /**
2537     * mention 用の span を作成する。
2538     * @param Number id Rettyのuser ID
2539     * @param Number name 名前。Rettyのユーザー名と一致していなくても問題無し。
2540     * @return String
2541     */
2542    function _createMentionSpan(id, name) {
2543        return '<span class="mention" data-rtrevieweditor-mention="' + id + '">' + name + '</span>';
2544    }
2545
2546    /**
2547     * Parses the div element and returns a parsed value, which can be used for DB.
2548     * @return {text: "parsed text", mentions: [{id: nnn, name:"Name of the user mentioned"}]}
2549     */
2550    function _parseDiv(div) {
2551        _cleanupDiv(div);
2552
2553        var result = div.clone();
2554        var mentions = [];
2555        result.contents().each(function() {
2556            var $this = $(this);
2557            if ($this.is('div')) {
2558                var afterthis = $this;
2559                $this.contents().each(function(i, e) {
2560                    var newelem = $(e).clone();
2561                    afterthis.after(newelem);
2562                    afterthis = newelem;
2563                });
2564
2565                $this.replaceWith('\n');
2566            } else if($this.is('br')){
2567                $this.replaceWith('\n');
2568            } else if ($this.is('span[data-rtrevieweditor-mention]')) {
2569                var userId = $this.attr('data-rtrevieweditor-mention');
2570                var userName = $this.text();
2571                // console.log(userId + ',' + userName);
2572                $this.replaceWith('@[' + userId + ':' + escapeHtml(userName) + ']');
2573                mentions.push({id: userId, name: userName});
2574            } else {
2575                var content = $this.text();
2576                $this.text(content);
2577                // $this.replaceWith(escapeHtml(content));
2578            }
2579        });
2580        return {text: result.text(), mentions: mentions};
2581    }
2582
2583    /**
2584     * @param object div jQuery object of the content editable div
2585     */
2586    function _cleanupDiv(div) {
2587        div.contents().each(function(i, e) {
2588            var $this = $(this);
2589            if ($this.is('div')) {
2590                _getCurrentPosition(div);
2591                // Chrome, Safariの場合、divが入るので削除する。
2592                var afterthis = $this;
2593                $this.contents().each(function(i, e) {
2594                    var newelem = $(e).clone();
2595                    afterthis.after(newelem);
2596                    afterthis = newelem;
2597                });
2598                $this.replaceWith('<br>');
2599
2600                var nodeIndex = Number(_getData(div, 'position-node-index'));
2601                var offset = Number(_getData(div, 'position-offset'));
2602                _setCursorPosition(div[0], nodeIndex + 1, offset);
2603            }/* else if ($this.is('span[data-rtrevieweditor-mention]')) {*/
2604            if ($this.is('span[data-rtrevieweditor-mention]')) {
2605                var userId = $this.attr('data-rtrevieweditor-mention');
2606                var userName = $this.text();
2607                if (!userName) {
2608                    $this.remove();
2609                }
2610                // 先頭にスペースが入った場合
2611                var match = userName.match(/^(\s+)(.*)$/);
2612                if (match) {
2613                    $this.before(match[1]);
2614                    $this.text(match[2]);
2615                }
2616                // 末尾にスペースが入った場合
2617                match = userName.match(/^(.*)(\s+)$/);
2618                if (match) {
2619                    $this.text(match[1]);
2620                    $this.after(match[2]);
2621                }
2622                // 先頭か末尾に改行が入った場合
2623                if($this.contents().length ==2) {
2624                    var first = $this.contents()[0],
2625                        second = $this.contents()[1];
2626                    if (first.nodeType == 3 && $(second).is('br')) {
2627                        $this.text(first.textContent);
2628                        $(second).remove();
2629                        $this.after('<br>');
2630                    } else if ($(first).is('br') && second.nodeType == 3) {
2631                        $this.before('<br>');
2632                        $(first).remove();
2633                        $this.text(second.textContent);
2634                    }
2635                }
2636                // 途中に改行が入った場合等
2637                if($this.contents().length >= 3) {
2638                    $this.text($this.contents().text());
2639                }
2640            }
2641        });
2642    }
2643
2644    function _eventHandler(e) {
2645        // console.log('event fired');
2646        $(this).rtReviewEditor('refresh');
2647    }
2648
2649    // plugin setup
2650    $.fn.rtReviewEditor = function(method) {
2651        if(methods[method]) {
2652            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
2653        } else if (typeof method === 'object' || !method) {
2654            return methods.init.apply(this, arguments);
2655        } else {
2656            $.error('Method ' + method + 'does not exist on jQuery.foo');
2657        }
2658    };
2659})(jQuery);
2660
2661/**
2662 * 「人を選択する」ダイアログ
2663 */
2664function UserSelectDialog(options) {
2665    var self = this;
2666    this._users = null;
2667    this._users4autoComplete = null;
2668    this._popup = null;
2669    this._options = $.extend({
2670        'user-type': 'followings', // 一覧に誰を出すか
2671        'default-selectall': false,
2672        'use-autocomplete': false,
2673        'html-submit-button': _('追加する'),
2674        'html-title': '',
2675        'popup-css-class': '',
2676        'popup-options': {},
2677        'onsubmit': function() {},
2678        'onopen': function() {}
2679    }, options);
2680
2681    this.open = function() {
2682        if (!this._users) {
2683            var initializer = this._dataInitializers[this._options['user-type']];
2684            if (!initializer) {
2685                console.log('error');
2686                return;
2687            }
2688            $.getJSON(initializer['url'], initializer['data'], function(json) {
2689                initializer['callback'](json);
2690                self._showPopup();
2691            });
2692        } else {
2693            this._showPopup();
2694        }
2695    };
2696
2697    this.close = function() {
2698        this._popup.destroy();
2699    };
2700
2701    this.getCheckedUsers = function() {
2702        return $('.popup_select_users_list input:checkbox:checked').map(function(i, e) {
2703            var userId = e.value;
2704            var userName = $("label[for='popup_select_users_checkbox_" + userId + "']").text();
2705            return {user_id: userId, user_name: userName};
2706        });
2707    };
2708
2709    this._showPopup = function () {
2710        var html = RtMustache.to_html('popup_select_users', this._users);
2711        var $popupNode = $(html);
2712        this._popup = new Popup($popupNode, this._options['popup-options']);
2713        this._popup.show();
2714        $('.popup_select_users .exit_button').click(function() {
2715	        self._popup.destroy();
2716	    });
2717        $('.popup_select_users .submit').click(function() {
2718            self._options['onsubmit'](self);
2719        });
2720        if (this._options['default-selectall']) {
2721            this._toggleAllCheckboxes(true);
2722            $('.popup_select_users .control_unselect_all').show();
2723            $('.popup_select_users .control_unselect_all input:checkbox').click(function() {
2724                if (!$(this).is(':checked')) {
2725                    self._toggleAllCheckboxes(false);
2726                }
2727            });
2728        }
2729        if (this._options['html-title']) {
2730            $('.popup_select_users .title').html(this._options['html-title']).show();
2731        }
2732        $('.popup_select_users .submit').html(this._options['html-submit-button']);
2733        if (this._options['popup-css-class']) {
2734            $('.popup_select_users').addClass(this._options['popup-css-class']);
2735        }
2736        if (this._options['use-autocomplete']) {
2737            $('.popup_select_users .control_autocomplete').show();
2738            this._setupAutoComplete();
2739        }
2740
2741        this._options['onopen'](self);
2742    };
2743
2744    this._toggleAllCheckboxes = function(checked) {
2745        $('.popup_select_users_list input:checkbox').prop('checked', checked);
2746    };
2747
2748    this._setupAutoComplete = function() {
2749        $('#popup_select_users_filter_text').autocomplete({
2750            minLength: 0,
2751    	    source: function(request, response) {
2752                var text = $('#popup_select_users_filter_text').val();
2753                if (text.length == 0) {
2754                    $('.popup_select_users_list .user').show();
2755                    return;
2756                }
2757                var filtered = $.ui.autocomplete.filter(self._users4autoComplete, text);
2758                $('.popup_select_users_list .user').hide();
2759                for(i in filtered) {
2760                    var userId = filtered[i].value;
2761                    $('#popup_select_users_user_' + userId).show();
2762                }
2763                response([]);
2764            },
2765            focus: function() {
2766                return false;
2767            },
2768            select: function(event, ui) {
2769                return false;
2770            }
2771        });
2772        // x をクリックした時には、テキストボックスをクリアして全ての選択肢を表示する。
2773        $('.popup_select_users .clear_text').click(function() {
2774            $('#popup_select_users_filter_text').val('');
2775            $('.popup_select_users_list .user').show();
2776        });
2777    };
2778}
2779
2780function scrollToHead(){
2781    $('html,body').animate({scrollTop: 0}, 'slow','swing');
2782}
2783
2784function showPopupNoFbPostPermission() {
2785    var _popupElem = '<div>Facebookへの書き込み権限がありません。<a href="account.php" target="_blank">アカウントページ</a>から、連携の更新を行って下さい。</div>';
2786    var _p = new Popup(_popupElem, {'top': '25%', 'left': '25%', 'width': '50%', 'height': '50%',
2787                                    'color': 'black', 'background': 'white'});
2788    _p.show();
2789}

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.