hypweb.net
XOOPSマニア  最新情報のRSS(サイト全体)
[ 自宅サーバーWebRing |ID=54 前後5表示乱移動サイト一覧 ]

TOP » UsersWiki » calendar nao-pon/blog/2015.04
Archives
2003
1 2 3 4 5 6 7 8 9 10 11 12
2004
1 2 3 4 5 6 7 8 9 10 11 12
2005
1 2 3 4 5 6 7 8 9 10 11 12
2006
1 2 3 4 5 6 7 8 9 10 11 12
2007
1 2 3 4 5 6 7 8 9 10 11 12
2008
1 2 3 4 5 6 7 8 9 10 11 12
2009
1 2 3 4 5 6 7 8 9 10 11 12
2010
1 2 3 4 5 6 7 8 9 10 11 12
2011
1 2 3 4 5 6 7 8 9 10 11 12
2012
1 2 3 4 5 6 7 8 9 10 11 12
2013
1 2 3 4 5 6 7 8 9 10 11 12
2014
1 2 3 4 5 6 7 8 9 10 11 12
2015
1 2 3 4 5 6 7 8 9 10 11 12
2016
1 2 3 4 5 6 7 8 9 10 11 12
2017
1 2 3 4 5 6 7 8 9 10 11 12
2020
1 2 3 4 5 6 7 8 9 10 11 12
2021
1 2 3 4 5 6 7 8 9 10 11 12
2022
1 2 3 4 5 6 7 8 9 10 11 12
2023
1 2 3 4 5 6 7 8 9 10 11 12
<< 2015.4 >>
[nao-pon/blog]
      2 4
5 6 7 8 9 10 11
12 13 14 16 18
19 20 21 22 24 25
26 27 29 30    
 
RSS of nao-pon/blog

[jQuery] フォームの二重送信を防止する(小ワザつき) anchor.png

XOOPS の d3forum で二重送信してしまう場合が結構あったので、jQuery でちょっと対応してみた。

フォーム送信時に submit ボタンが disabled だと、そのボタンのデータが送信されず、例えば d3forum だと「プレビュー」を押してるのに「送信」扱いになってしまうので、setTimeout で、disable 属性の付与をちょっとだけ遅延させてあります。

また、別窓で開くフォーム用に target 属性を持つフォームは除外し、念のため 15 秒後に再活性化するようにしてあります。

これを、HypCommon の設定の「その他の設定」-「<head>内の最後に挿入するタグ」に記述しておくと XOOPS サイト全体にこの機能が追加されます。

追記
[jQuery] Web ページのフォーム投稿時問題のあれこれを上手いことするやつ でもっといい感じのものを作ってみました。
Everything is expanded.Everything is shortened.
1
2
3
4
5
6
7
8
9
 
-
-
|
|
|
!
!
 
<script type="text/javascript">
jQuery(function($){
  $('form:not([target])').on('submit',function(e){
    var btn = $(this).find('input[type="submit"]');
    setTimeout(function(){btn.attr('disabled', 'disabled')},100);
    setTimeout(function(){btn.removeAttr('disabled');},15000);
  });
});
</script>

 
RSS of nao-pon/blog

[jQuery] Web ページのフォーム投稿時問題のあれこれを上手いことするやつ anchor.png

長文の投稿を書いている時に、間違ってブラウザ閉じてしまったり、ページ移動してしまったり、送信したらサーバーとの接続が切れてしまった!

OH MY GOD!

会心の出来だ!と喜んだのも束の間、奈落の底に突き落とされるような思いをすることが、たまにありますよね。

このような事態にみまわれると、投稿分の出来がよければよいほど、立ち直るのにしばらく時間が掛かってしまいます。

そんな、思いをしないため、させないために、ちょっとゴリゴリ jQuery で書いてみました。

Textarea復原ボタン.png

移動してもいい?.png
テキストエリアに入力中にページ移動しようとしたりしてページが閉じられる前にブラウザが閉じていいのかを聞いてくれます。
さらに、万が一閉じてしまったり送信時にサーバーと接続できなかったりした時でも、次に開いた時にテキストエリアの下に「復元」ボタンが表示されるので、それをクリックすれば、ほらっ元通り!

<script type="text/javascript" charset="utf-8" src="hyp_form_rescue.js"></script>

などと、UTF-8 指定で <head> 内の jQuery を読み込んだ後に置くだけで OK です。 :ok:

filehyp_form_rescue.js
Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
-
|
|
|
|
|
!
-
|
-
-
|
|
!
!
-
-
-
-
|
!
!
!
|
|
|
!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
|
|
-
|
!
-
|
!
|
|
-
|
|
-
|
|
|
!
|
|
!
-
|
!
-
|
!
-
|
|
-
|
|
|
|
-
-
|
!
!
-
|
|
-
|
|
!
|
!
-
|
|
!
|
|
-
|
|
|
-
|
-
-
|
|
|
|
!
-
-
|
|
|
!
!
!
|
|
|
|
-
-
|
|
!
!
-
-
-
|
|
!
!
!
!
!
!
-
!
-
-
|
|
-
|
-
|
|
|
!
!
!
|
!
!
/*!
 * Web ページのフォーム投稿時問題のあれこれを上手いことするやつ
 * 
 * Copyright (c) 2015 Naoki Sawada hypweb.net
 * Released under the MIT license
 * http://opensource.org/licenses/mit-license.php
 */
jQuery(function($){
    /** 二重投稿防止用 **/
    $('form:not([target])').each(function(){
        if (this.onsubmit) {
            $(this).data('hyp_onsubmit', this.onsubmit.bind(this));
            this.onsubmit = null;
        }
    });
    $(window).on('submit', 'form:not([target])', function(e){
        if ($(this).data('hyp_onsubmit')) {
            try {
                if (!$(this).data('hyp_onsubmit')()) {
                    return false;
                }
            } catch(e){}
        }
        var btn = $(this).find('input[type="submit"]');
        setTimeout(function(){btn.prop('disabled', true)},100);
        setTimeout(function(){btn.prop('disabled', false);},20000);
    });
 
    /** 入力途中のページ移動防止とテキストエリアに「復元」ボタン追加 **/
    var
    /* ページを閉じるときのアラートメッセージ(Firefox は指定メッセージは表示されない) */
    msg   = 'テキストエリアに入力中のデータがあります。\n\n※ 次回、同様のページを開いた時にテキストエリアの内容は[復元]ボタンで復元できます。',
    /* ボタンテキスト */
    btnTx = '復元',
    /* ボタンの title 属性値 */
    btnTi = '最後に入力したデータを復元します。\nテキストエリアが未入力の場合に利用できます。'
    /* ボタン CSS クラス */
    btnCl = 'hypRescueBtn',
    /* 自動保存(秒): 初回2分後、その後30秒毎 (及びページ移動時) */
    autoS = [120000, 30000],
    /* textarea 入力中フラグ */
    flgC  = 'hyp-changed',
    /* localStorage の保存キー */
    dataK = 'hyp-textarea-rescue',
    /* CSS */
    css   = (function () {/*
form div.hypRescueBtn {
	float: right;
	width: auto;
	font-size: 11px;
	margin-top: 2px;
	margin-right: 1px;
	padding: 1px 5px;
	border: 1px solid gray;
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
	border-radius: 4px;
	cursor: pointer;
	background: #fcfff4;
	background: -moz-linear-gradient(top,  #fcfff4 27%, #dfe5d7 93%, #b3bead 100%);
	background: -webkit-gradient(linear, left top, left bottom, color-stop(27%,#fcfff4), color-stop(93%,#dfe5d7), color-stop(100%,#b3bead));
	background: -webkit-linear-gradient(top,  #fcfff4 27%,#dfe5d7 93%,#b3bead 100%);
	background: -o-linear-gradient(top,  #fcfff4 27%,#dfe5d7 93%,#b3bead 100%);
	background: -ms-linear-gradient(top,  #fcfff4 27%,#dfe5d7 93%,#b3bead 100%);
	background: linear-gradient(to bottom,  #fcfff4 27%,#dfe5d7 93%,#b3bead 100%);
	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fcfff4', endColorstr='#b3bead',GradientType=0 );
}
form div.hypRescueBtn:hover {
	padding: 0px 4px;
	border: 2px solid orange;
	border-top-color: gold;
	border-left-color: gold;
}
form div.hypRescueBtn.disabled {
	color: #aaa;
	cursor: default;
}
form div.hypRescueBtn.disabled:hover {
	border: 1px solid #808080;
	padding: 1px 5px;
}
*/}).toString().match(/\/\*([^]*)\*\//)[1];
 
    var htr = {},
    isEmpty = function(val) {
        return val.match(/^\s*$/);
    }
    try{
        htr = JSON.parse(localStorage.getItem(dataK));
    }catch(e){}
    if (!htr || typeof htr != 'object') htr = {};
    $('<style>').append(css).appendTo($('head')[0]);
    $(window).on('beforeunload', function(){
        if (typeof localStorage == 'undefined') return;
        var ret;
        $('form textarea').each(function(){
            var tArea = $(this);
            if (tArea.data(flgC) && !isEmpty(tArea.val())) ret = true;
            if (!isEmpty(tArea.val())) htr[this.name] = tArea.val();
        });
        localStorage.setItem(dataK, JSON.stringify(htr));
        if (ret) return msg;
    });
    $('body').on('change', 'form textarea', function(){
        $(this).val() && $(this).data(flgC, true);
    });
    $('body').on('submit', 'form', function(){
        $(this).find('textarea').data(flgC, false);
    });
    $('body').one('focus', 'textarea', function(){
        var tArea = $(this),
            flg   = 'hyp_rescue';
        if (!tArea.data(flg)) {
            var res,cur,ck,
            ckArea = $('#cke_' + tArea.attr('id'))[0],
            name = this.name,
            bef  = null,
            tgl  = function(on){
                if (res) {
                    on? res.removeClass('disabled') : res.addClass('disabled');
                }
            },
            save = function(){
                ck = ckArea? CKEDITOR.instances[tArea.attr('id')] : null;
                ck && tArea.val(ck.getData());
                if (!isEmpty(tArea.val())) {
                    htr[name] = tArea.val();
                    localStorage.setItem(dataK, JSON.stringify(htr));
                }
                setTimeout(save, autoS[1]);
            };
            if (ckArea || typeof CKEDITOR == 'object') {
                ckArea = $(ckArea);
                ck = CKEDITOR.instances[tArea.attr('id')];
            }
            tArea.data(flg, true).change();
            setTimeout(save, autoS[1]);
            if (htr[name]) {
                res = $('<div>')
                .addClass(btnCl)
                .attr('title', btnTi)
                .on('click', function(){
                    ck = ckArea? CKEDITOR.instances[tArea.attr('id')] : null;
                    if (ck) {
                        if (isEmpty(ck.getData())) {
                            (tArea.data('editor') == 'html')? ck.insertHtml(htr[name]) : ck.insertText(htr[name]);
                            tArea.data(flgC, true);
                            ck.focus();
                            tgl(false);
                        }
                    } else {
                        if (isEmpty(tArea.val())) {
                            tArea.val(htr[name]).data(flgC, true);
                            tArea.focus();
                            tgl(false);
                        }
                    }
                })
                .append(btnTx)
                .insertAfter(ckArea|| tArea);
                if (!(bef = isEmpty(tArea.val()))) res.addClass('disabled');
                res.fadeIn(750).fadeOut(250).fadeIn(750);
                tArea.on('keyup change', function(){
                    if (bef !== (cur = isEmpty(tArea.val()))) {
                        bef = cur;
                        tgl(bef);
                    }
                });
                if (ck) {
                    (tArea.data('ckon') || ck.on)('change', function(){
                        if (bef !== (cur = isEmpty(ck.getData()))) {
                            bef = cur;
                            tgl(bef);
                        }
                    });
                }
            }
        }
    });
    // for Ajax post
    var oldSend = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function(){
        if (arguments[0] && arguments[0].split) {
            var q = arguments[0].split('&'),
            i = 0, t;
            for(i; i < q.length; i ++) {
                t = q[i].split('=');
                $('form textarea[name=\''+t[0]+'\']').each(function(){
                    var tArea = $(this);
                    tArea.data(flgC, false);
                    if (!isEmpty(tArea.val())) htr[t[0]] = tArea.val();
                });
            }
        }
        oldSend.apply(this, arguments);
    };
});
Page Top

更新履歴 anchor.png

  • 2015-04-03 初版
  • 2015-04-04 Ajax 送信に対応
  • 2015-05-11 ckeditor4 モジュール 0.61 以上との組み合わせで CKEditor での投稿フォームに対応
  • 2015-05-11 onsubmit 属性が指定された <FORM> で submit がキャンセルされた場合にフォームボタンが一定時間押せなくなって困ってしまう :hammer: 問題を修正
  • 2015-05-12 CKEditor で編集中でも定期的な自動保存に対応
  • 2015-05-18 Ajax 通信時に不具合がでることがある問題を修正
    • 具体的には、name 属性に英数文字以外の文字が含まれる場合に正常に送信できていませんでした。XOOPS X だと、X-update での一括処理で送信エラーになっていました。

 
RSS of nao-pon/blog

XCL (XOOPS Cube Legacy) の PHP 5.6 対応 anchor.png

logo-php56.png

Raspberry Pi 2 をウェブサーバーに仕立てて、PHP 5.6 系で XOOPS X を動かしてみると、大量の "Unknown Condition [8192]: Non-static method 〜" というエラーが表示されます。*1

「ん〜これは修正したい!」という欲望に駆られて着手してしまいました。 :-D

まずは、コアと XOOPS X でメンテナンスしているモジュールから手を付けます。

一番多いエラーは、MyTextSanitizer::getInstance() のエラーです。

MyTextSanitizer クラスの getInstance() に static キーワードが付いていないのに、静的に呼び出しているのが原因です。PHP 5.6 以前は、E_STRICT エラーだったものが、5.6 以降は E_DEPRECATED エラーとして出力されるようになったので、5.6 以降の環境では、大量にエラーレポートされるようになったわけです。*2

当初は、"error_reporting(E_ALL ^ E_STRICT ^ E_DEPRECATED)" にしてしまおうと思いましたが、E_DEPRECATED を隠してしまうと、将来サポートされなくなる問題点がわかりづらくなってしまうので、error_reporting はそのままにして、コード修正を行うことにしました。

本来なら MyTextSanitizer::getInstance() に static キーワードを付ければいいのですが、MyTextSanitizer クラスはモジュール側で継承クラスを持っていることが多く、安易に static キーワードを付けてしまうと Fatal エラーになってしまいます。

そこで、新しく static なメソッド sGgetInstance() を作って対応することにしました。

モジュール側では、

$ts =& MyTextSanitizer::getInstance();

としているところを

(method_exists('MyTextSanitizer', 'sGetInstance') and $ts =& MyTextSanitizer::sGetInstance()) || $ts =& MyTextSanitizer::getInstance();

などとします。

正規表現で置換するなら

(\$[\w>-]+)\s*=(\s*&)?\s*MyTextSanitizer\s*::\s*getInstance\s*\(\s*\)

(method_exists('MyTextSanitizer', 'sGetInstance') and $1 =$2 MyTextSanitizer::sGetInstance()) || $0

に置換するとよいと思います。

これらの一連の修正を、コアに関しては XOOPS X の pilot ブランチ、そして XOOPS X リポジトリのモジュールに対して行いました。ただ、まだまだ修正漏れやその他のエラーが表示されますので引き続きひまひまに作業していきます。

X-update で更新できます*3ので、テスト環境をお持ちの方は、ぜひ問題点をレポートして頂けると助かります。


 
RSS of nao-pon/blog

[jQuery] hover を on で処理しいときのメモ書き anchor.png

logo-jQuery.png
jQuery で、動的に追加される DOM に対して、onready 関数内で hover イベントで処理する関数を登録しようとして、何も考えずに

$(parent).on('hover', '[セレクタ]', function(){...});

って書いたけど、案の定全然動かなかった。そりゃそうだ、hover イベントなんてない、jQuery オブジェクトの関数だ。 :hammer:

で、今度はちゃんと考えて

Everything is expanded.Everything is shortened.
-
|
|
-
-
!
-
-
!
!
!
$(parent).on('mouseenter mouseleave', '[セレクタ]', function(e){
var self = $(this);
    var self = $(this);
    if (e.type === 'mouseenter') {
        // マウスポインタが乗った時の処理
        self.ほげほげ;
    } else {
        // マウスポインタが外れた時の処理
        self.ふがふが;
    }
});

ってやったらちゃんとできた。というメモ書き。


 
RSS of nao-pon/blog

[XCL:テーマ] marine さんの Snowland をちょっと改造 anchor.png

xc_legacy.jpg
PHP 5.6 系での動作確認のため、Raspberry Pi 2 に XOOPS X を入れて快調に動いている Raspoops ですが、XOOPS 123 marine さん作のテーマも全部入れて、その中から Snowland をデフォルトテーマにしています。

Snowland は、画面上方に各モジュールへのメニューが表示され、画面を下にスクロールして隠れそうになると position: fixed に切り替わり、常に場面上部に表示されるのでとても使い勝手がいいです。

当初、数個のモジュールを入れた状態では問題なかったのですが、動作検証ということで X-update でどんどん入れたら、メニュー部がど〜ん!って感じになってしまいました。 :-P

2bc506da.png

まあ、こんなに節操もなく数多くのモジュールを入れる人は、そうはいないでしょうからね。まったく、イレギュラーの状況だと思います。

そこで、ちょっとだけ手を入れさせて頂きました。

  • position: fixed で場面上部に張り付く時は1行分だけ表示
  • その表示範囲は、カレントモジュールのメニューが表示される位置
  • 1行表示の時にマウスオーバーすると、ちょっと間を置いて広げて全部表示
  • マウスカーソルを外すと、ちょっと間を置いて1行表示に戻る
  • 検索ボックスの下にメニューが隠れないように
  • メニューボックスが、上部固定モードに切り替わる時、メニューボックスの高さ分 body 要素の表示位置が上へずれるのを防止

と、だいたいこんな感じです。

9181360d.png

すっきりして、本文表示部が広くなりました (∩´∀`)∩ワーイ

素敵なテーマを数多く公開されている marine さんに、感謝感激です。 :shy:


自分自身へのメモ書きとして、今回改造した内容の diff を置いておきます。
手を入れたファイルは、file_style.cssfiletheme_ext_js.html の2つです。(_style.css は style.css です。style.css を添付するとこのページのスタイルシートとして使用されてしまうのでリネームしています。)

filesnowland.diff
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
diff -u html/xoopsx/themes/snowland/style.css html/xoopsx/themes/snowland_hyp/style.css
--- html/xoopsx/themes/snowland/style.css	2015-04-17 22:11:50.013566177 +0900
+++ html/xoopsx/themes/snowland_hyp/style.css	2015-04-17 14:48:06.590316600 +0900
@@ -365,6 +365,7 @@
 	-webkit-box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.3);
 	-moz-box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.3);
 	box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.3);
+	overflow: hidden;
 }
 
 #latest	{ 
diff -u html/xoopsx/themes/snowland/theme_ext_js.html html/xoopsx/themes/snowland_hyp/theme_ext_js.html
--- html/xoopsx/themes/snowland/theme_ext_js.html	2015-04-17 22:11:50.053567053 +0900
+++ html/xoopsx/themes/snowland_hyp/theme_ext_js.html	2015-04-18 11:40:08.448889079 +0900
@@ -70,32 +70,68 @@
 });
 </script>
 <script type="text/javascript">
-jQuery(function() {
-	var nav = jQuery('.nav');
-	var headerSearch = jQuery('#headerSearch');
-	var navTop = nav.offset().top;
-	var GuideSentence = '<{$smarty.const._THEME_LANGUAGE_SEARCH}>';
-	var long = '200px';
-	var short = '156px';
-	jQuery(window).scroll(function () {
-		var winTop = jQuery(this).scrollTop();
+jQuery(function($) {
+	var nav = $('header#header div.nav'),
+		headerSearch = $('#headerSearch'),
+		GuideSentence = '<{$smarty.const._THEME_LANGUAGE_SEARCH}>',
+		long = '200px',
+		short = '156px',
+		lineH = nav.find('ul li:first').height(),
+		navH = nav.height(),
+		navTop = nav.offset().top + navH - lineH,
+		dum = $('<div>').addClass('nav').css({height: navH + 'px'}).hide().insertBefore(nav),
+		fixpos = function() {
+			var act, tm,
+				ul = nav.find('ul:first');
+			if (nav.hasClass('fixed') && !nav.hasClass('expand') && (act = nav.find('a.act:first'))) {
+				ul.css({marginRight: long});
+				act.length && ul.css({marginTop: nav.offset().top - act.offset().top});
+				nav.css({height: lineH+'px'});
+			} else {
+				ul.css({marginTop: 0, marginRight: nav.hasClass('fixed')? long : '10px'});
+				nav.css({height: 'auto'});
+			}
+		};
+	$(window).scroll(function () {
+		var winTop = $(this).scrollTop();
 		if (winTop >= navTop) {
-			nav.addClass('fixed'),headerSearch.addClass('hs_top'),headerSearch.removeClass('hs_normal')
-		} else if (winTop <= navTop) {
-			nav.removeClass('fixed'),headerSearch.addClass('hs_normal'),headerSearch.removeClass('hs_top')
+			if (!nav.hasClass('fixed')) {
+				dum.show();
+				nav.addClass('fixed'),headerSearch.addClass('hs_top').removeClass('hs_normal');
+				fixpos();
+			}
+		} else {
+			if (nav.hasClass('fixed')) {
+				dum.hide();
+				nav.removeClass('fixed'),headerSearch.addClass('hs_normal').removeClass('hs_top');
+				fixpos();
+			}
 		}
 	});
-	jQuery('input#headerSearch-keywords').focus(function(){
-	    if(jQuery(this).val()===GuideSentence){
-	        jQuery(this).val('');
-	    }
-	    jQuery(this).animate({width: long},400);
+	$('input#headerSearch-keywords').on('focus blur', function(e){
+			if (e.type == 'focus') {
+				$(this).val()===GuideSentence && $(this).val('');
+				$(this).animate({width: long},400);
+		} else {
+				$(this).val()==='' && $(this).val(GuideSentence);
+				$(this).animate({width: short},500);
+		}
+	});
+	$('header#header').on('mouseenter mouseleave', 'div.fixed', function(e){
+		var ev = e.type;
+		if (nav.data('tm')) {
+			clearTimeout(nav.data('tm'));
+			nav.data('tm', null);
+			return;
+		}
+		nav.data('tm', setTimeout(function() {
+			nav.data('tm', null);
+			ev === 'mouseenter'? !nav.hasClass('expand') && nav.addClass('expand') : nav.hasClass('expand') && nav.removeClass('expand');
+			fixpos();
+		}, 800));
 	});
-	jQuery('input#headerSearch-keywords').blur(function(){
-	    if(jQuery(this).val()===''){
-	        jQuery(this).val(GuideSentence);
-	    }
-	    jQuery(this).animate({width: short},500);
+	nav.on('mousedown', 'a', function(e){
+		nav.data('tm') && clearTimeout(nav.data('tm'));
 	});
 });
 </script>

 
RSS of nao-pon/blog

Nginx でリバースプロキシ経由時の REMOTE_ADDR を正しく得る anchor.png

nginx_logo.png
Raspberry Pi2 で動いている Raspoops ですが、宅外からのアクセスは、この xoops.hypweb.net が動いている Apache をリバースプロキシにして Raspi の Neginx に転送しています。

今日、出先からちょっと調べたいことがあって Raspoops にアクセスしたら、あれ〜? Protector に BAN されてる!

BanByProtector.png

ん?おかしいな?と思い帰宅後、宅内の PC から Raspoops の Protector を確認してみたら、「拒否 IP リスト」に 1行だけ等よくされていました。

192.168.x.x:1432299382

って。

あ!リバースプロキシにしてる Apache のサーバー IP じゃん!

Protector の設定では、ローカル IP は BAN 対象から外しているので、HypCommonFunc のスパム対策で登録されたのだと思います。

あぁ、そうか! Nginx に通知される REMORT_ADDR は、リバースプロキシのそれなんだぁ!と今更気付きました。 :lol:

ということで、対策。

Apache からは、 X-Forwarded-For ヘッダで、アクセス元の IP が通知されているので、Nginx のほうでそれを REMOTE_ADDR にアサインすれば OK です。

server ディレクティブで

set_real_ip_from 192.168.x.x;
real_ip_header X-Forwarded-For;

ってして Nginx を再起動すれば OK :ok: これで REMOTE_ADDR に実サクセス元 IP がセットされるので、Protector, HypCommonFunc のスパム対策が正常に働きます。

あーよかった。 :shy:

リバースプロキシで転送している場合は、REMOTE_ADDR を正しくセットしないと XOOPS でのスパム対策が意味を成さないから気をつけましょうというお話でした。


 
RSS of nao-pon/blog

おお〜! PHP 7 早い! anchor.png

PHPNG(PHP7).jpeg
Raspberry Pi2 に、早くなってると巷で噂の PHP 7.0.0 をインストールして確かめてみました。

Nginx + PHP-FPM でバーチャルホスト機能を使いドキュメントルートは共用にして、pi2.hypweb.net を PHP 5.6.7 で、phpng.pi2.hypweb.net を PHP 7.0.0 で同じコンテンツが動くようにしてあります。

まずは、自前のプログラムからということで、xpWiki のデフォルトページの中でレンダリングに時間が掛かる FormattingRules のページで見てみました。

管理者でアクセスするとページ下部に表示されるレンダリング時間での計測です。

まずは、PHP 5.6.7

  1. 0.625
  2. 0.633
  3. 0.634
  4. 0.637
  5. 0.672
  • 平均 0.6402 秒
    xpWiki 5.02.19 Copyright &#169; 2006-2014 hypweb.net. License is GPL.
    Based on "PukiWiki" 1.4.8_alpha. Powered by PHP 7.0.0-dev. HTML convert time: 0.255 sec.

次は、PHP 7.0.0

  1. 0.250
  2. 0.267
  3. 0.264
  4. 0.275
  5. 0.255
  • 平均 0.2622 秒!
    xpWiki 5.02.19 Copyright &#169; 2006-2014 hypweb.net. License is GPL.
    Based on "PukiWiki" 1.4.8_alpha. Powered by PHP 7.0.0-dev. HTML convert time: 0.255 sec. 

おお!早いですねぇ :ok:

ページを移動してると、体感できるぐらい早いです。本リリースが楽しみですね。

ただ、XOOPS Cube Legacy は、PHP 4 時代のコードが残っているところがあるので、PHP 7 になったことで、かなり Deprecated エラーがレポートされます。動くには動くのですが、PHP デバグが有効だとエラー表示をコントロールしないと厳しいですね。

PHP 7 から、クラスのコンストラクタとしてクラス名と同じメソッドは、非奨励となったのでそのレポートが多いですね。エラーがレポートされないようにコードを修正すべきですが、今回のはかなり大変そうです。

とりあえず、PHP 7 はえ〜! というお話でした。



*1 PHPデバグをOnにした場合
*2 XCL の PHPデバグでのエラーレポートレベルは "error_reporting(E_ALL ^ E_STRICT)"
*3 pilot ブランチは、正式リリースの前に評価して頂くことを目的にしたブランチで、X-update の一般設定「非表示ストア(開発・先行版)も表示する」を「はい」にすることで表示される「For developer」モジュールストアに含まれています。

トップ 印刷に適した表示   ページ新規作成 全ページ一覧 単語検索 最新ページの一覧   ヘルプ   最新ページのRSS 1.0 最新ページのRSS 2.0 最新ページのRSS Atom Powered by xpWiki
このページのTopへ
メインメニュー
ログイン

ユーザー名:


パスワード:





パスワード紛失  |新規登録
最近の更新
オンライン状況
432 人のユーザが現在オンラインです。 (11 人のユーザが UsersWiki を参照しています。)

登録ユーザ: 0
ゲスト: 432

もっと...
サイト情報