text:
'use strict';

const Router = require('express').Router;
const createError = require('http-errors');
const debug = require('debug')('puptracker:auth-router');
const jsonParser = require('body-parser').json();

const basicAuth = require('../lib/basic-auth-middleware.js');

const User = require('../model/user.js');

const authRouter = module.exports = Router();

//dont need this route, no signup option
authRouter.post('/api/signup', jsonParser, function(req, res, next){
  debug('POST /api/signup');

  //they will send username, password, and we give them token back
  let password = req.body.password;
  delete req.body.password;

  let user = new User(req.body);

  user.generatePasswordHash(password)
  .then(user => user.save())
  .then(user => user.generateToken())
  .then(token => res.send(token))
  .catch(next);
});

//just have login option, one username and password
authRouter.get('/api/login', basicAuth, function(req, res, next){
  debug('GET /api/login');

  User.findOne({username: req.auth.username})
  .then(user => user.comparePasswordHash(req.auth.password))
  .catch(err => Promise.reject(createError(401, err.message)))
  .then(user => user.generateToken())
  .then(token => res.send(token))
  .catch(next);
});


text:
NgProc API is a Ruby on Rails Json API that uses JWT (Json Web Token) as token-based authentication system.

- [Installing](#installing)
- [Technologies](#technologies)
- [Other Notes](#other-notes)
- [License](#license)

## Installing

Installing the dependencies:

```bash
bundle install

```

Setting up the database:

```bash
rails db:create
rails db:migrate
rails db:seed

```

The application has an action at AutheticationController#auth to make the authentication. Use the admin_user (email: admin@admin.com, password: 123456) to get the JWT.

## Technologies

* Ruby: 2.3.3
* Rails: 5.0.0.1
* MySQL: 5.7.17
* Devise
* JWT
* RSpec

## Other Notes

## License

MIT

redpajama_set_name: RedPajamaGithub


text: resty ./autodoc/admin-api/openapi-gen.lua kong-admin-api.yml


text:
layout: showcase
title: "Spotlights"
description: "Listing of all spotlights."
id: spotlight
collection: showcase
published: true
---

    {% include modules/breadcrumbs.liquid %}

Spotlights

Sites and apps we love, regardless of their mainstream success. Always pushing the web forward. Click through for interviews with the developers and pro/cons.

        {% for tag in site.data['tags'] %}
          #{{tag}}
        {% endfor %}

Have an idea for a spotlight? Let us know!

{% assign spotlights = page.articles.spotlight | sort: 'date' | reverse  %}

        {% for spotlight in spotlights %}

{{spotlight.title}}

{{spotlight.description}}

        {% endfor %}

{% include cc.liquid %}


text:
//
//  XHMessageTableViewController.m
//  MessageDisplayExample
//
//  Created by qtone-1 on 14-4-24.
//  Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
//

#import "XHMessageTableViewController.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import "XHVoiceRecordHelper.h"
#import "XHVoiceRecordHUD.h"

@interface XHMessageTableViewController ()
@property (nonatomic, assign) BOOL isUserScrolling;//判断是否用户手指滚动
@property (nonatomic, assign) CGFloat previousTextViewContentHeight;//记录旧的textView contentSize Heigth
@property (nonatomic, assign) CGFloat keyboardViewHeight;//记录键盘的高度,为了适配iPad和iPhone
@property (nonatomic, assign) XHInputViewType textViewInputViewType;

@property (nonatomic, weak, readwrite) XHMessageInputView *messageInputView;
@property (nonatomic, weak, readwrite) XHShareMenuView *shareMenuView;
@property (nonatomic, weak, readwrite) XHEmotionManagerView *emotionManagerView;

@property (nonatomic, strong, readwrite) XHVoiceRecordHUD *voiceRecordHUD;
@property (nonatomic, strong) XHVoiceRecordHelper *voiceRecordHelper;//管理录音工具对象
@end

@implementation XHMessageTableViewController

#pragma mark - DataSource Change
//改变数据源需要的子线程
- (void)exChangeMessageDataSourceQueue:(void (^)())queue {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), queue);
}
//执行块代码在主线程
- (void)exMainQueue:(void (^)())queue {
    dispatch_async(dispatch_get_main_queue(), queue);
}

static CGPoint  delayOffset = {0.0};
// http://stackoverflow.com/a/11602040 Keep UITableView static when inserting rows at the top
- (void)insertOldMessages:(NSArray *)oldMessages completion:(void (^)())completion {
    WEAKSELF
    [self exChangeMessageDataSourceQueue:^{
        delayOffset = weakSelf.messageTableView.contentOffset;
        NSMutableArray *indexPaths = [[NSMutableArray alloc] initWithCapacity:oldMessages.count];
        NSMutableIndexSet *indexSets = [[NSMutableIndexSet alloc] init];
        [oldMessages enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
            [indexPaths addObject:indexPath];
            delayOffset.y += [weakSelf calculateCellHeightWithMessage:[oldMessages objectAtIndex:idx] atIndexPath:indexPath];
            [indexSets addIndex:idx];
        }];
        NSMutableArray *messages = [[NSMutableArray alloc] initWithArray:weakSelf.messages];
        [messages insertObjects:oldMessages atIndexes:indexSets];
        [weakSelf exMainQueue:^{
            [UIView setAnimationsEnabled:NO];
            weakSelf.messageTableView.userInteractionEnabled = NO;
            [weakSelf.messageTableView beginUpdates];
            weakSelf.messages = messages;
            [weakSelf.messageTableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
            [weakSelf.messageTableView endUpdates];
            [UIView setAnimationsEnabled:YES];
            [weakSelf.messageTableView setContentOffset:delayOffset animated:NO];
            weakSelf.messageTableView.userInteractionEnabled = YES;
            if (completion) {
                completion();
            }
        }];
    }];
}

#pragma mark - Propertys
- (NSMutableArray *)messages {
    if (!_messages) {
        _messages = [[NSMutableArray alloc] initWithCapacity:0];
    }
    return _messages;
}
- (XHShareMenuView *)shareMenuView {
    if (!_shareMenuView) {
        XHShareMenuView *shareMenuView = [[XHShareMenuView alloc] initWithFrame:CGRectMake(0,
                                                                                CGRectGetHeight(self.view.bounds),
                                                                                CGRectGetWidth(self.view.bounds),
                                                                                /*self.keyboardViewHeight*/
                                                                                120)];
        shareMenuView.delegate = self;
        shareMenuView.backgroundColor = [UIColor colorWithWhite:0.961 alpha:1.000];
        shareMenuView.alpha = 0.0;
        [self.view addSubview:shareMenuView];
        _shareMenuView = shareMenuView;
    }
    [self.view bringSubviewToFront:_shareMenuView];
    return _shareMenuView;
}
- (XHEmotionManagerView *)emotionManagerView {
    if (!_emotionManagerView) {
        XHEmotionManagerView *emotionManagerView = [[XHEmotionManagerView alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.view.bounds), CGRectGetWidth(self.view.bounds), self.keyboardViewHeight)];
        emotionManagerView.delegate = self;
        emotionManagerView.dataSource = self;
        emotionManagerView.backgroundColor = [UIColor colorWithWhite:0.961 alpha:1.000];
        emotionManagerView.alpha = 0.0;
        [self.view addSubview:emotionManagerView];
        _emotionManagerView = emotionManagerView;
    }
    [self.view bringSubviewToFront:_emotionManagerView];
    return _emotionManagerView;
}
- (XHVoiceRecordHUD *)voiceRecordHUD {
    if (!_voiceRecordHUD) {
        _voiceRecordHUD = [[XHVoiceRecordHUD alloc] initWithFrame:CGRectMake(0, 0, 140, 140)];
    }
    return _voiceRecordHUD;
}
- (XHVoiceRecordHelper *)voiceRecordHelper {
    if (!_voiceRecordHelper) {
        WEAKSELF
        _voiceRecordHelper = [[XHVoiceRecordHelper alloc] init];
        _voiceRecordHelper.maxTimeStopRecorderCompletion = ^{
            DLog(@"已经达到最大限制时间了,进入下一步的提示");
            [weakSelf finishRecorded];
        };
        _voiceRecordHelper.peakPowerForChannel = ^(float peakPowerForChannel) {
            weakSelf.voiceRecordHUD.peakPower = peakPowerForChannel;
        };
        _voiceRecordHelper.maxRecordTime = kVoiceRecorderTotalTime;
        _voiceRecordHelper.minRecordTime = kVoiceRecorderMinTime;
    }
    return _voiceRecordHelper;
}

#pragma mark - Messages View Controller
- (void)finishSendMessageWithBubbleMessageType:(XHBubbleMessageMediaType)mediaType {
    switch (mediaType) {
        case XHBubbleMessageMediaTypeText: {
            [self.messageInputView.inputTextView setText:nil];
            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
                self.messageInputView.inputTextView.enablesReturnKeyAutomatically = NO;
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    self.messageInputView.inputTextView.enablesReturnKeyAutomatically = YES;
                    [self.messageInputView.inputTextView reloadInputViews];
                });
            }
            break;
        }
        case XHBubbleMessageMediaTypePhoto: {
            break;
        }
        case XHBubbleMessageMediaTypeVideo: {
            break;
        }
        case XHBubbleMessageMediaTypeVoice: {
            break;
        }
        case XHBubbleMessageMediaTypeEmotion: {
            break;
        }
        case XHBubbleMessageMediaTypeLocalPosition: {
            break;
        }
        default:
            break;
    }
}
- (void)scrollToBottomAnimated:(BOOL)animated {
	if (![self shouldAllowScroll])
        return;

    NSInteger rows = [self.messageTableView numberOfRowsInSection:0];

    if (rows > 0) {
        [self.messageTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:rows - 1 inSection:0]
                              atScrollPosition:UITableViewScrollPositionBottom
                                      animated:animated];
    }
}
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath
			  atScrollPosition:(UITableViewScrollPosition)position
					  animated:(BOOL)animated {
	if (![self shouldAllowScroll])
        return;

	[self.messageTableView scrollToRowAtIndexPath:indexPath
						  atScrollPosition:position
								  animated:animated];
}

#pragma mark - Previte Method
- (BOOL)shouldAllowScroll {
    if (self.isUserScrolling) {
        return NO;
    }

    return YES;
}

#pragma mark - Life Cycle
- (void)initilzer {
    self.navigationController.navigationBar.translucent = YES;//NOTE:与下面的参数必须配套设置,否则top会有64个像素的偏移量
    self.automaticallyAdjustsScrollViewInsets = NO;

    self.keyboardViewHeight = (kIsiPad ? 264 : 216);
    _allowsPanToDismissKeyboard = NO;
    _allowsSendVoice = YES;
    _allowsSendMultiMedia = YES;
    _allowsSendFace = YES;
    _inputViewStyle = XHMessageInputViewStyleFlat;

    // 默认设置用户滚动为NO
    _isUserScrolling = NO;

    // 初始化message tableView
    self.messageTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
	self.messageTableView.dataSource = self;
	self.messageTableView.delegate = self;
    self.messageTableView.separatorColor = [UIColor clearColor];
    self.messageTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    [self.view addSubview:self.messageTableView];
    [self.view sendSubviewToBack:self.messageTableView];
    [self.messageTableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top);
        make.left.equalTo(self.view.mas_left);
        make.bottom.equalTo(self.view.mas_bottom);
        make.right.equalTo(self.view.mas_right);
    }];
    // 设置整体背景颜色
    self.view.backgroundColor = kDefaultViewColor;
    self.messageTableView.backgroundColor = [UIColor clearColor];

    //注册自定义消息cell
    [EZGMessageTextCell registerCellToTableView:self.messageTableView];
    [EZGMessageVoiceCell registerCellToTableView:self.messageTableView];
    [EZGMessageImageCell registerCellToTableView:self.messageTableView];
    [EZGMessageLocationCell registerCellToTableView:self.messageTableView];
    [EZGMessageVideoCell registerCellToTableView:self.messageTableView];
    [EZGMessageSceneCell registerCellToTableView:self.messageTableView];
    [EZGMessageCarCell registerCellToTableView:self.messageTableView];
    [EZGMessageServiceCell registerCellToTableView:self.messageTableView];
    [EZGMessageServiceCancelCell registerCellToTableView:self.messageTableView];
    [EZGMessageServiceCommentCell registerCellToTableView:self.messageTableView];

    // 设置Message TableView 的bottom edg
    CGFloat inputViewHeight = 45.0f;
    [self setTableViewInsetsWithBottomValue:inputViewHeight];

    // 输入工具条的frame
    CGRect inputFrame = CGRectMake(0.0f,
                                   self.view.frame.size.height - inputViewHeight,
                                   self.view.frame.size.width,
                                   inputViewHeight);

    WEAKSELF
    if (self.allowsPanToDismissKeyboard) {
        // 控制输入工具条的位置块
        void (^AnimationForMessageInputViewAtPoint)(CGPoint point) = ^(CGPoint point) {
            CGRect inputViewFrame = weakSelf.messageInputView.frame;
            CGPoint keyboardOrigin = [weakSelf.view convertPoint:point fromView:nil];
            inputViewFrame.origin.y = keyboardOrigin.y - inputViewFrame.size.height;
            weakSelf.messageInputView.frame = inputViewFrame;
        };

        self.messageTableView.keyboardDidScrollToPoint = ^(CGPoint point) {
            if (weakSelf.textViewInputViewType == XHInputViewTypeText)
                AnimationForMessageInputViewAtPoint(point);
        };

        self.messageTableView.keyboardWillSnapBackToPoint = ^(CGPoint point) {
            if (weakSelf.textViewInputViewType == XHInputViewTypeText)
                AnimationForMessageInputViewAtPoint(point);
        };

        self.messageTableView.keyboardWillBeDismissed = ^() {
            CGRect inputViewFrame = weakSelf.messageInputView.frame;
            inputViewFrame.origin.y = weakSelf.view.bounds.size.height - inputViewFrame.size.height;
            weakSelf.messageInputView.frame = inputViewFrame;
        };
    }
    self.messageTableView.keyboardWillChange = ^(CGRect keyboardRect, UIViewAnimationOptions options, double duration, BOOL showKeyborad) {
        if (weakSelf.textViewInputViewType == XHInputViewTypeText) {
            [UIView animateWithDuration:duration
                                  delay:0.0
                                options:options
                             animations:^{
                                 CGFloat keyboardY = [weakSelf.view convertRect:keyboardRect fromView:nil].origin.y;

                                 CGRect inputViewFrame = weakSelf.messageInputView.frame;
                                 CGFloat inputViewFrameY = keyboardY - inputViewFrame.size.height;

                                 // for ipad modal form presentations
                                 CGFloat messageViewFrameBottom = weakSelf.view.frame.size.height - inputViewFrame.size.height;
                                 if (inputViewFrameY > messageViewFrameBottom)
                                     inputViewFrameY = messageViewFrameBottom;

                                 weakSelf.messageInputView.frame = CGRectMake(inputViewFrame.origin.x,
                                                                              inputViewFrameY,
                                                                              inputViewFrame.size.width,
                                                                              inputViewFrame.size.height);

                                 [weakSelf setTableViewInsetsWithBottomValue:weakSelf.view.frame.size.height
                                  - weakSelf.messageInputView.frame.origin.y];
                                 if (showKeyborad)
                                     [weakSelf scrollToBottomAnimated:NO];
                             }
                             completion:nil];
        }
    };
    self.messageTableView.keyboardDidChange = ^(BOOL didShowed) {
        if ([weakSelf.messageInputView.inputTextView isFirstResponder]) {
            if (didShowed) {
                if (weakSelf.textViewInputViewType == XHInputViewTypeText) {
                    weakSelf.shareMenuView.alpha = 0.0;
                    weakSelf.emotionManagerView.alpha = 0.0;
                }
            }
        }
    };
    self.messageTableView.keyboardDidHide = ^() {
        [weakSelf.messageInputView.inputTextView resignFirstResponder];
    };

    // 初始化输入工具条
    XHMessageInputView *inputView = [[XHMessageInputView alloc] initWithFrame:inputFrame];
    inputView.allowsSendFace = self.allowsSendFace;
    inputView.allowsSendVoice = self.allowsSendVoice;
    inputView.allowsSendMultiMedia = self.allowsSendMultiMedia;
    inputView.delegate = self;
    [self.view addSubview:inputView];
    [self.view bringSubviewToFront:inputView];
    _messageInputView = inputView;

    // 设置手势滑动,默认添加一个bar的高度值
    self.messageTableView.messageInputBarHeight = CGRectGetHeight(_messageInputView.bounds);
}
- (void)viewDidLoad {
    [super viewDidLoad];
    [self initilzer];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(finishRecordingWhenErrorBehaviors) name:UIApplicationWillResignActiveNotification object:nil];
}
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // 设置键盘通知或者手势控制键盘消失
    [self.messageTableView setupPanGestureControlKeyboardHide:self.allowsPanToDismissKeyboard];

    // KVO 检查contentSize
    [self.messageInputView.inputTextView addObserver:self
                                          forKeyPath:@"contentSize"
                                             options:NSKeyValueObservingOptionNew
                                             context:nil];

    [self.messageInputView.inputTextView setEditable:YES];
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self finishRecordingWhenErrorBehaviors];
    if (self.textViewInputViewType != XHInputViewTypeNormal) {
        [self layoutOtherMenuViewHiden:YES];
    }

    // remove键盘通知或者手势
    [self.messageTableView disSetupPanGestureControlKeyboardHide:self.allowsPanToDismissKeyboard];

    // remove KVO
    [self.messageInputView.inputTextView removeObserver:self forKeyPath:@"contentSize"];
    [self.messageInputView.inputTextView setEditable:NO];
}
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
    _messages = nil;
    _messageTableView.delegate = nil;
    _messageTableView.dataSource = nil;
    _messageTableView = nil;
    _messageInputView = nil;
}

#pragma mark - RecorderPath Helper Method
- (NSString *)getRecorderPath {
    NSString *recorderPath = nil;
    NSDate *now = [NSDate date];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    recorderPath = [[NSString alloc] initWithFormat:@"%@/Documents/IMRecorderPath", NSHomeDirectory()];
    dateFormatter.dateFormat = @"yyyy-MM-dd-HH-mm-ss";
    recorderPath = [recorderPath stringByAppendingFormat:@"%@-MySound.aac", [dateFormatter stringFromDate:now]];
    return recorderPath;
}

#pragma mark - UITextView Helper Method
//获取某个UITextView对象的content高度
- (CGFloat)getTextViewContentH:(UITextView *)textView {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        return ceilf([textView sizeThatFits:textView.frame.size].height);
    }
    else {
        return textView.contentSize.height;
    }
}

#pragma mark - Layout Message Input View Helper Method
//动态改变TextView的高度
- (void)layoutAndAnimateMessageInputTextView:(UITextView *)textView {
    CGFloat maxHeight = [XHMessageInputView maxHeight];
    CGFloat contentH = [self getTextViewContentH:textView];
    BOOL isShrinking = contentH < self.previousTextViewContentHeight;
    CGFloat changeInHeight = contentH - _previousTextViewContentHeight;
    if (!isShrinking && (self.previousTextViewContentHeight == maxHeight || textView.text.length == 0)) {
        changeInHeight = 0;
    }
    else {
        changeInHeight = MIN(changeInHeight, maxHeight - self.previousTextViewContentHeight);
    }

    if (changeInHeight != 0.0f) {
        [UIView animateWithDuration:0.25f
                         animations:^{
                             [self setTableViewInsetsWithBottomValue:self.messageTableView.contentInset.bottom + changeInHeight];

                             [self scrollToBottomAnimated:NO];

                             if (isShrinking) {
                                 if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0) {
                                     self.previousTextViewContentHeight = MIN(contentH, maxHeight);
                                 }
                                 // if shrinking the view, animate text view frame BEFORE input view frame
                                 [self.messageInputView adjustTextViewHeightBy:changeInHeight];
                             }

                             CGRect inputViewFrame = self.messageInputView.frame;
                             self.messageInputView.frame = CGRectMake(0.0f,
                                                                      inputViewFrame.origin.y - changeInHeight,
                                                                      inputViewFrame.size.width,
                                                                      inputViewFrame.size.height + changeInHeight);
                             if (!isShrinking) {
                                 if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0) {
                                     self.previousTextViewContentHeight = MIN(contentH, maxHeight);
                                 }
                                 // growing the view, animate the text view frame AFTER input view frame
                                 [self.messageInputView adjustTextViewHeightBy:changeInHeight];
                             }
                         }
                         completion:^(BOOL finished) {
                         }];

        self.previousTextViewContentHeight = MIN(contentH, maxHeight);
    }

    // Once we reached the max height, we have to consider the bottom offset for the text view.
    // To make visible the last line, again we have to set the content offset.
    if (self.previousTextViewContentHeight == maxHeight) {
        double delayInSeconds = 0.01;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime,
                       dispatch_get_main_queue(),
                       ^(void) {
                           CGPoint bottomOffset = CGPointMake(0.0f, contentH - textView.bounds.size.height);
                           [textView setContentOffset:bottomOffset animated:YES];
                       });
    }
}

#pragma mark - Message Calculate Cell Height
//统一计算Cell的高度方法
- (CGFloat)calculateCellHeightWithMessage:(AVIMTypedMessage *)message atIndexPath:(NSIndexPath *)indexPath {
    CGFloat cellHeight = 0;
    BOOL displayTimestamp = [self shouldDisplayTimestampForRowAtIndexPath:indexPath];
    if (kAVIMMessageMediaTypeText == message.mediaType) {
        cellHeight = [EZGMessageTextCell HeightOfCellByMessage:message displaysTimestamp:displayTimestamp];
    }
    else if (kAVIMMessageMediaTypeAudio == message.mediaType) {
        cellHeight = [EZGMessageVoiceCell HeightOfCellByMessage:message displaysTimestamp:displayTimestamp];
    }
    else if (kAVIMMessageMediaTypeImage == message.mediaType) {
        cellHeight = [EZGMessageImageCell HeightOfCellByMessage:message displaysTimestamp:displayTimestamp];
    }
    else if (kAVIMMessageMediaTypeLocation == message.mediaType) {
        cellHeight = [EZGMessageLocationCell HeightOfCellByMessage:message displaysTimestamp:displayTimestamp];
    }
    else if (kAVIMMessageMediaTypeVideo == message.mediaType) {
        cellHeight = [EZGMessageVideoCell HeightOfCellByMessage:message displaysTimestamp:displayTimestamp];
    }
    else if (EZGMessageTypeScene == message.mediaType) {
        cellHeight = [EZGMessageSceneCell HeightOfCellByMessage:message displaysTimestamp:displayTimestamp];
    }
    else if (EZGMessageTypeCar == message.mediaType) {
        cellHeight = [EZGMessageCarCell HeightOfCellByMessage:message displaysTimestamp:displayTimestamp];
    }
    else if (EZGMessageTypeService == message.mediaType) {
        cellHeight = [EZGMessageServiceCell HeightOfCellByMessage:message displaysTimestamp:displayTimestamp];
    }
    else if (EZGMessageTypeServiceCancel == message.mediaType) {
        cellHeight = [EZGMessageServiceCancelCell HeightOfCellByMessage:message displaysTimestamp:displayTimestamp];
    }
    else if (EZGMessageTypeServiceComment == message.mediaType) {
        cellHeight = [EZGMessageServiceCommentCell HeightOfCellByMessage:message displaysTimestamp:displayTimestamp];
    }

    return cellHeight;
}
//是否显示时间轴Label的回调方法
- (BOOL)shouldDisplayTimestampForRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

#pragma mark - Message Send
//根据文本开始发送文本消息
- (void)didSendMessageWithText:(NSString *)text {
    DLog(@"send text : %@", text);

}
//根据图片开始发送图片消息
- (void)didSendMessageWithPhoto:(UIImage *)photo {
    DLog(@"send photo : %@", photo);

}
//根据录音路径开始发送语音消息
- (void)didSendMessageWithVoice:(NSString *)voicePath voiceDuration:(NSString*)voiceDuration {
    DLog(@"send voicePath : %@", voicePath);

}
//根据地理位置信息和地理经纬度开始发送地理位置消息
- (void)didSendGeolocationsMessageWithGeolocaltions:(NSString *)geolocations location:(CLLocation *)location {
    DLog(@"send geolcations : %@", geolocations);

}
//发送表情
- (void)didSendEmotionMessageWithEmotion:(NSString *)emotion {
    DLog(@"send emotion : %@", emotion);
}
//根据视频的封面和视频的路径开始发送视频消息(未启用)
- (void)didSendMessageWithVideoConverPhoto:(UIImage *)videoConverPhoto videoPath:(NSString *)videoPath  {
    DLog(@"send videoPath : %@  videoConverPhoto : %@", videoPath, videoConverPhoto);

}

#pragma mark - Other Menu View Frame Helper Mehtod
//根据显示或隐藏的需求对所有第三方Menu进行管理
- (void)layoutOtherMenuViewHiden:(BOOL)hide {
    [self.messageInputView.inputTextView resignFirstResponder];
    [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        __block CGRect inputViewFrame = self.messageInputView.frame;
        __block CGRect otherMenuViewFrame;

        void (^InputViewAnimation)(BOOL hide) = ^(BOOL hide) {
            inputViewFrame.origin.y = (hide ? (CGRectGetHeight(self.view.bounds) - CGRectGetHeight(inputViewFrame)) : (CGRectGetMinY(otherMenuViewFrame) - CGRectGetHeight(inputViewFrame)));
            self.messageInputView.frame = inputViewFrame;
        };

        void (^EmotionManagerViewAnimation)(BOOL hide) = ^(BOOL hide) {
            otherMenuViewFrame = self.emotionManagerView.frame;
            otherMenuViewFrame.origin.y = (hide ? CGRectGetHeight(self.view.frame) : (CGRectGetHeight(self.view.frame) - CGRectGetHeight(otherMenuViewFrame)));
            self.emotionManagerView.alpha = !hide;
            self.emotionManagerView.frame = otherMenuViewFrame;
        };

        void (^ShareMenuViewAnimation)(BOOL hide) = ^(BOOL hide) {
            otherMenuViewFrame = self.shareMenuView.frame;
            otherMenuViewFrame.origin.y = (hide ? CGRectGetHeight(self.view.frame) : (CGRectGetHeight(self.view.frame) - CGRectGetHeight(otherMenuViewFrame)));
            self.shareMenuView.alpha = !hide;
            self.shareMenuView.frame = otherMenuViewFrame;
        };

        if (hide) {
            switch (self.textViewInputViewType) {
                case XHInputViewTypeEmotion: {
                    EmotionManagerViewAnimation(hide);
                    break;
                }
                case XHInputViewTypeShareMenu: {
                    ShareMenuViewAnimation(hide);
                    break;
                }
                default:
                    break;
            }
        } else {
            // 这里需要注意block的执行顺序,因为otherMenuViewFrame是公用的对象,所以对于被隐藏的Menu的frame的origin的y会是最大值
            switch (self.textViewInputViewType) {
                case XHInputViewTypeEmotion: {
                    // 1、先隐藏和自己无关的View
                    ShareMenuViewAnimation(!hide);
                    // 2、再显示和自己相关的View
                    EmotionManagerViewAnimation(hide);
                    break;
                }
                case XHInputViewTypeShareMenu: {
                    // 1、先隐藏和自己无关的View
                    EmotionManagerViewAnimation(!hide);
                    // 2、再显示和自己相关的View
                    ShareMenuViewAnimation(hide);
                    break;
                }
                default:
                    break;
            }
        }

        InputViewAnimation(hide);

        [self setTableViewInsetsWithBottomValue:self.view.frame.size.height - self.messageInputView.frame.origin.y];
        [self scrollToBottomAnimated:NO];
    } completion:^(BOOL finished) {
        if (hide) {
            self.textViewInputViewType = XHInputViewTypeNormal;
        }
    }];
}

#pragma mark - Voice Recording Helper Method
- (void)prepareRecordWithCompletion:(XHPrepareRecorderCompletion)completion {
    [self.voiceRecordHelper prepareRecordingWithPath:[self getRecorderPath] prepareRecorderCompletion:completion];
}
- (void)startRecord {
    self.messageTableView.scrollEnabled = NO;
    [self.voiceRecordHUD startRecordingHUDAtView:self.view];
    [self.voiceRecordHelper startRecordingWithStartRecorderCompletion:^{
    }];
}
- (void)finishRecorded {
    WEAKSELF
    [self.voiceRecordHUD stopRecordCompled:^(BOOL fnished) {
        weakSelf.voiceRecordHUD = nil;
        weakSelf.messageInputView.isRecording = NO;
        weakSelf.messageInputView.isCancelled = NO;
        weakSelf.messageTableView.scrollEnabled = YES;
    }];
    [self.voiceRecordHelper stopRecordingWithStopRecorderCompletion:^{
        [weakSelf didSendMessageWithVoice:weakSelf.voiceRecordHelper.recordPath voiceDuration:weakSelf.voiceRecordHelper.recordDuration];
    }];
}
- (void)pauseRecord {
    [self.voiceRecordHUD pauseRecord];
}
- (void)resumeRecord {
    [self.voiceRecordHUD resaueRecord];
}
- (void)cancelRecord {
    WEAKSELF
    [self.voiceRecordHUD cancelRecordCompled:^(BOOL fnished) {
        weakSelf.voiceRecordHUD = nil;
        weakSelf.messageInputView.isRecording = NO;
        weakSelf.messageInputView.isCancelled = YES;
        weakSelf.messageTableView.scrollEnabled = YES;
    }];
    [self.voiceRecordHelper cancelledDeleteWithCompletion:^{

    }];
}
//当其它错误操作发生时,停止录音
- (void)finishRecordingWhenErrorBehaviors {
    if (self.messageInputView.isRecording) {
        [self didFinishRecoingVoiceAction];
    }
}

#pragma mark - XHMessageInputView Delegate
- (void)inputTextViewWillBeginEditing:(XHMessageTextView *)messageInputTextView {
    self.textViewInputViewType = XHInputViewTypeText;
}
- (void)inputTextViewDidBeginEditing:(XHMessageTextView *)messageInputTextView {
    if (!self.previousTextViewContentHeight)
		self.previousTextViewContentHeight = [self getTextViewContentH:messageInputTextView];
}
- (void)didChangeSendVoiceAction:(BOOL)changed {
    DLog(@"didChangeSendVoiceAction");
    if (changed) {
        if (self.textViewInputViewType == XHInputViewTypeText)
            return;
        // 在这之前,textViewInputViewType已经不是XHTextViewTextInputType
        [self layoutOtherMenuViewHiden:YES];
    }
}
- (void)didInputAtSign:(XHMessageTextView *)messageInputTextView {
    DLog(@"didInputAtSign");
}
- (void)didSendTextAction:(NSString *)text {
    DLog(@"text : %@", text);
    [self didSendMessageWithText:text];
}
- (void)didSelectedMultipleMediaAction {
    DLog(@"didSelectedMultipleMediaAction");
    self.textViewInputViewType = XHInputViewTypeShareMenu;
    [self layoutOtherMenuViewHiden:NO];
}
- (void)didSendFaceAction:(BOOL)sendFace {
    DLog(@"didSendFaceAction");
    if (sendFace) {
        self.textViewInputViewType = XHInputViewTypeEmotion;
        [self layoutOtherMenuViewHiden:NO];
    } else {
        [self.messageInputView.inputTextView becomeFirstResponder];
    }
}
- (void)prepareRecordingVoiceActionWithCompletion:(BOOL (^)(void))completion {
    DLog(@"prepareRecordingWithCompletion");
    [self prepareRecordWithCompletion:completion];
}
- (void)didStartRecordingVoiceAction {
    DLog(@"didStartRecordingVoice");
    [self startRecord];
}
- (void)didCancelRecordingVoiceAction {
    DLog(@"didCancelRecordingVoice");
    [self cancelRecord];
}
- (void)didFinishRecoingVoiceAction {
    DLog(@"didFinishRecoingVoice");
    if (self.voiceRecordHelper.currentTimeInterval < self.voiceRecordHelper.minRecordTime) {
        [UIView showResultThenHideOnWindow:@"录音时间太短" afterDelay:0.5];
        [self cancelRecord];
    }
    else {
        [self finishRecorded];
    }
}
- (void)didDragOutsideAction {
    DLog(@"didDragOutsideAction");
    [self resumeRecord];
}
- (void)didDragInsideAction {
    DLog(@"didDragInsideAction");
    [self pauseRecord];
}

#pragma mark - XHEmotionManagerView Delegate
- (void)didSelecteEmotion:(XHEmotion *)emotion atIndexPath:(NSIndexPath *)indexPath {
    if (emotion.emotionPath) {
        [self didSendEmotionMessageWithEmotion:emotion.emotionPath];
    }
}
- (void)didSelectEmotionStoreButton:(UIButton *)button{
    [self didSendMessageWithText:self.messageInputView.inputTextView.text];
}

#pragma mark - XHEmotionManagerView DataSource
- (NSInteger)numberOfEmotionManagers {
    return 0;
}
- (XHEmotionManager *)emotionManagerForColumn:(NSInteger)column {
    return nil;
}
- (NSArray *)emotionManagersAtManager {
    return nil;
}

#pragma mark - UIScrollView Delegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
	self.isUserScrolling = YES;

    UIMenuController *menu = [UIMenuController sharedMenuController];
    if (menu.isMenuVisible) {
        [menu setMenuVisible:NO animated:YES];
    }

    if (self.textViewInputViewType != XHInputViewTypeNormal) {
        [self layoutOtherMenuViewHiden:YES];
    }
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    self.isUserScrolling = NO;
}

#pragma mark - Table View Data Source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.messages.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    AVIMTypedMessage *message = self.messages[indexPath.row];
    BOOL displayTimestamp = [self shouldDisplayTimestampForRowAtIndexPath:indexPath];

    EZGMessageBaseCell *cell = nil;
    if (kAVIMMessageMediaTypeText == message.mediaType) {
        cell = [EZGMessageTextCell dequeueCellByTableView:tableView];
    }
    else if (kAVIMMessageMediaTypeAudio == message.mediaType) {
        cell = [EZGMessageVoiceCell dequeueCellByTableView:tableView];
    }
    else if (kAVIMMessageMediaTypeImage == message.mediaType) {
        cell = [EZGMessageImageCell dequeueCellByTableView:tableView];
        EZGMessageImageCell *imageCell = (EZGMessageImageCell *)cell;
        imageCell.block = ^{
            [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];//FIXME:bug?
            //TODO:如何判断当处于bottom就始终scroll to bottom;不处于bottom就只刷新cell???
//            [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
        };
    }
    else if (kAVIMMessageMediaTypeLocation == message.mediaType) {
        cell = [EZGMessageLocationCell dequeueCellByTableView:tableView];
    }
    else if (kAVIMMessageMediaTypeVideo == message.mediaType) {
        cell = [EZGMessageVideoCell dequeueCellByTableView:tableView];
    }
    else if (EZGMessageTypeScene == message.mediaType) {
        cell = [EZGMessageSceneCell dequeueCellByTableView:tableView];
    }
    else if (EZGMessageTypeCar == message.mediaType) {
        cell = [EZGMessageCarCell dequeueCellByTableView:tableView];
    }
    else if (EZGMessageTypeService == message.mediaType) {
        cell = [EZGMessageServiceCell dequeueCellByTableView:tableView];
    }
    else if (EZGMessageTypeServiceCancel == message.mediaType) {
        cell = [EZGMessageServiceCancelCell dequeueCellByTableView:tableView];
    }
    else if (EZGMessageTypeServiceComment == message.mediaType) {
        cell = [EZGMessageServiceCommentCell dequeueCellByTableView:tableView];
    }
    [cell layoutMessage:message displaysTimestamp:displayTimestamp];

    return cell;
}

#pragma mark - Table View Delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [self calculateCellHeightWithMessage:self.messages[indexPath.row] atIndexPath:indexPath];
}

#pragma mark - Key-value Observing
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    if (object == self.messageInputView.inputTextView && [keyPath isEqualToString:@"contentSize"]) {
        [self layoutAndAnimateMessageInputTextView:object];
    }
}

#pragma mark - Scroll Message TableView Helper Method
//根据bottom的数值配置消息列表的内部布局变化
- (void)setTableViewInsetsWithBottomValue:(CGFloat)bottom {
    UIEdgeInsets insets = [self tableViewInsetsWithBottomValue:bottom];
    self.messageTableView.contentInset = insets;
    self.messageTableView.scrollIndicatorInsets = insets;
}
//根据底部高度获取UIEdgeInsets常量
- (UIEdgeInsets)tableViewInsetsWithBottomValue:(CGFloat)bottom {
    UIEdgeInsets insets = UIEdgeInsetsZero;
    insets.top = 64;
    insets.bottom = bottom;
    return insets;
}

@end


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<meta name="generator"

content="HTML Tidy for Mac OS, see www.w3.org" />

<title>XHTML Functional -- IMG - HEIGHT=percent</title>

image with no height specification

 image height=100%

 image height=25%

 image height=0%

 image height=-100%

 image height=(74.000001%) [floating point]


text:
SYNONYM

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
null

#### Original name
Cyphella ochroleuca Berk. & Broome, 1854

### Remarks
null


text:
var express = require('express');
var router = express.Router();
var config = require('../config')

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', {
    title: config.title,
    currentPath: ""
 });
});

router.get('/guide', function(req, res, next){
    res.render('guide', {
        title: 'Info - ' + config.title,
        gmapsscripturl: 'https://maps.googleapis.com/maps/api/js?key=' + config.gmapskey + '&callback=initBoth&signed_in=true',
        currentPath: 'guide'
    });
});

router.get('/wishlist', function(req, res, next){
    res.render('wishlist', {
      title: 'Gave - ' + config.title,
      currentPath: 'wishlist'
    });
});

router.get('/sleep', function(req, res, next){
    res.render('sleep', {
        title: 'Overnatting - ' + config.title,
        gmapsscripturl: 'https://maps.googleapis.com/maps/api/js?key=' + config.gmapskey + '&callback=initMap&signed_in=true',
        currentPath: 'sleep'
    });
});

module.exports = router;


text:
package org.dcm4chee.web.war.tc;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.IAjaxCallDecorator;
import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow.WindowClosedCallback;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.Radio;
import org.apache.wicket.markup.html.form.RadioGroup;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.image.Image;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.util.convert.converters.DateConverter;
import org.dcm4chee.icons.ImageManager;
import org.dcm4chee.icons.behaviours.ImageSizeBehaviour;
import org.dcm4chee.web.common.markup.BaseForm;
import org.dcm4chee.web.dao.tc.TCQueryFilter;
import org.dcm4chee.web.dao.tc.TCQueryFilterKey;
import org.dcm4chee.web.dao.tc.TCQueryFilterValue;
import org.dcm4chee.web.dao.tc.TCQueryFilterValue.YesNo;
import org.dcm4chee.web.war.common.AutoSelectInputTextBehaviour;
import org.dcm4chee.web.war.tc.TCUtilities.NullDropDownItem;
import org.dcm4chee.web.war.tc.widgets.TCAjaxComboBox;
import org.dcm4chee.web.war.tc.widgets.TCMaskingAjaxDecorator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Bernhard Ableitinger <bernhard.ableitinger@agfa.com>
 * @version $Revision$ $Date$
 * @since April 28, 2011
 */
public abstract class TCSearchPanel extends Panel {

    private static final long serialVersionUID = 1L;

	private static final SimpleDateFormat dfDE = new SimpleDateFormat("dd.MM.yyyy");
	private static final SimpleDateFormat dfDefault = new SimpleDateFormat("MM/dd/yyyy");

    private static final Logger log = LoggerFactory
            .getLogger(TCSearchPanel.class);

    private static enum Option {
        AuthorName, AuthorContact, AuthorAffiliation, History, Discussion, Title, Abstract, PatientSpecies
    }

    private boolean showSearch = true;

    private boolean showAdvancedOptions = false;

    @SuppressWarnings({ "serial" })
	public TCSearchPanel(final String id) {
        super(id, new Model<TCQueryFilter>(new TCQueryFilter()));

        setOutputMarkupId(true);

        final DateSpanSearchItem dateSpanItem = new DateSpanSearchItem();
        final DateSpanDialog dateSpanDialog = new DateSpanDialog(dateSpanItem);
        final List<IDateSearchItem> dateItems = new ArrayList<IDateSearchItem>();
        dateItems.addAll(Arrays.asList(NotOlderThanSearchItem.values()));
        dateItems.add(dateSpanItem);

        Form<?> dateSpanDialogOuterForm = new Form<Void>("date-input-dialog-outer-form");
        dateSpanDialogOuterForm.setOutputMarkupId(true);
        dateSpanDialogOuterForm.setMarkupId("tc-search-date-input-form-helper");
        dateSpanDialogOuterForm.add(dateSpanDialog);

        final TCInput keywordInput = TCUtilities.createInput(
                "keywordInput", TCQueryFilterKey.Keyword, getFilterValue(TCQueryFilterKey.Keyword), true);
        final TCInput anatomyInput = TCUtilities.createInput(
                "anatomyInput", TCQueryFilterKey.Anatomy, getFilterValue(TCQueryFilterKey.Anatomy), true);
        final TCInput pathologyInput = TCUtilities.createInput(
                "pathologyInput", TCQueryFilterKey.Pathology, getFilterValue(TCQueryFilterKey.Pathology), true);
        final TCInput findingInput = TCUtilities.createInput(
                "findingInput", TCQueryFilterKey.Finding, getFilterValue(TCQueryFilterKey.Finding), true);
        final TCInput diagnosisInput = TCUtilities.createInput(
                "diagnosisInput", TCQueryFilterKey.Diagnosis, getFilterValue(TCQueryFilterKey.Diagnosis), true);
        final TCInput diffDiagnosisInput = TCUtilities.createInput(
                "diffDiagnosisInput", TCQueryFilterKey.DifferentialDiagnosis, getFilterValue(TCQueryFilterKey.DifferentialDiagnosis), true);
        final TextField<String> textText = new TextField<String>("textText",
                new Model<String>(""));
        textText.add(new AutoSelectInputTextBehaviour());

        final DropDownChoice<TCQueryFilterValue.AcquisitionModality> modalityChoice = TCUtilities.createDropDownChoice(
                "modalityChoice",
                new Model<TCQueryFilterValue.AcquisitionModality>(),
                Arrays.asList(TCQueryFilterValue.AcquisitionModality.values()),
                NullDropDownItem.All);
        final DropDownChoice<TCQueryFilterValue.PatientSex> patientSexChoice = TCUtilities.createEnumDropDownChoice(
                "patientSexChoice", new Model<TCQueryFilterValue.PatientSex>(),
                Arrays.asList(TCQueryFilterValue.PatientSex.values()), true,
                "tc.patientsex", NullDropDownItem.All);
        final DropDownChoice<TCQueryFilterValue.Category> categoryChoice = TCUtilities.createEnumDropDownChoice(
                "categoryChoice", new Model<TCQueryFilterValue.Category>(),
                Arrays.asList(TCQueryFilterValue.Category.values()), true,
                "tc.category", NullDropDownItem.All);
        final DropDownChoice<TCQueryFilterValue.Level> levelChoice = TCUtilities.createEnumDropDownChoice(
                "levelChoice", new Model<TCQueryFilterValue.Level>(),
                Arrays.asList(TCQueryFilterValue.Level.values()), true,
                "tc.level", NullDropDownItem.All);
        final DropDownChoice<TCQueryFilterValue.YesNo> diagnosisConfirmedChoice = TCUtilities.createEnumDropDownChoice(
                "diagnosisConfirmedChoice",
                new Model<TCQueryFilterValue.YesNo>(),
                Arrays.asList(TCQueryFilterValue.YesNo.values()), true,
                "tc.yesno", NullDropDownItem.All);
		final TCAjaxComboBox<IDateSearchItem> dateBox = new TCAjaxComboBox<IDateSearchItem>(
        		"dateChoice", dateItems, new IChoiceRenderer<IDateSearchItem>() {
        			public String getIdValue(IDateSearchItem item, int index) {
        				return item.getId();
        			}
        			public String getDisplayValue(IDateSearchItem item) {
        				return item.getLabel(getSession().getLocale());
        			}
        		}) {
        	@Override
        	protected IDateSearchItem convertValue(String svalue) {
        		if (TCUtilities.equals(dateSpanItem.getLabel(getSession().getLocale()),svalue)) {
        			return dateSpanItem;
        		}
        		else {
        			return NotOlderThanSearchItem.valueForLabel(
        					svalue, getSession().getLocale());
        		}
        	}
        	@Override
        	protected boolean shallCommitValue(IDateSearchItem oldValue, IDateSearchItem newValue, AjaxRequestTarget target) {
        		if (dateSpanItem==newValue) {
        			final Component c = this;
        			dateSpanDialog.setWindowClosedCallback(new WindowClosedCallback() {
        				@Override
        				public void onClose(AjaxRequestTarget target) {
        			        target.appendJavascript(getDateBoxInitUIJavascript(
        			        		c.getMarkupId(true), dateSpanItem, false));
        				}
        			});
        			dateSpanDialog.show(target);
            		return true;
        		}

        		return super.shallCommitValue(oldValue, newValue, target);
        	}
        };
        TCUtilities.addOnDomReadyJavascript(dateBox, getDateBoxInitUIJavascript(
        		dateBox.getMarkupId(), dateSpanItem, true));

        final RadioGroup<Option> optionGroup = new RadioGroup<Option>(
                "optionGroup", new Model<Option>());
        optionGroup.add(new Radio<Option>("historyOption", new Model<Option>(
                Option.History)));
        optionGroup.add(new Radio<Option>("authorNameOption",
                new Model<Option>(Option.AuthorName)));
        optionGroup.add(new Radio<Option>("authorContactOption",
                new Model<Option>(Option.AuthorContact)));
        optionGroup.add(new Radio<Option>("authorOrganisationOption",
                new Model<Option>(Option.AuthorAffiliation)));
        optionGroup.add(new Radio<Option>("discussionOption",
                new Model<Option>(Option.Discussion)));
        optionGroup.add(new Radio<Option>("titleOption", new Model<Option>(
                Option.Title)));
        optionGroup.add(new Radio<Option>("abstractOption", new Model<Option>(
                Option.Abstract)));
        optionGroup.add(new Radio<Option>("patientSpeciesOption",
                new Model<Option>(Option.PatientSpecies)));

        final AjaxButton searchBtn = new AjaxButton(
                "doSearchBtn") {

            private static final long serialVersionUID = 1L;

            private IAjaxCallDecorator decorator;

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                try {
                	try {
                		findParent(TCPanel.class).getPopupManager().hidePopups(target);
                	}
                	catch (Exception e) {
                		log.error("Error while closing popups!", e);
                	}

                    TCQueryFilter filter = (TCQueryFilter) TCSearchPanel.this
                            .getDefaultModelObject();
                    filter.clear();

                    filter.setKeywords(keywordInput.getValues());

                    if (showAdvancedOptions)
                    {
	                    filter.setAnatomy(anatomyInput.getValue());
	                    filter.setPathology(pathologyInput.getValue());
	                    filter.setFinding(findingInput.getValue());
	                    filter.setDiagnosis(diagnosisInput.getValue());
	                    filter.setDiffDiagnosis(diffDiagnosisInput.getValue());
		                    filter.setAcquisitionModality(modalityChoice
	                            .getModelObject());
	                    filter.setPatientSex(patientSexChoice.getModelObject());
	                    filter.setCategory(categoryChoice.getModelObject());
	                    filter.setLevel(levelChoice.getModelObject());

	                    YesNo yesNo = diagnosisConfirmedChoice.getModelObject();
	                    if (YesNo.Yes.equals(yesNo))
	                    {
	                    	filter.setDiagnosisConfirmed( yesNo );
	                    }

	                    IDateSearchItem dateItem = dateBox.getModelObject();
	                    if (dateItem==null) {
	                    	filter.setCreationDate(null, null);
	                    }
	                    else {
	                    	filter.setCreationDate(dateItem.getFromDate(),
	                    			dateItem.getUntilDate());
	                    }

	                    Option selectedOption = optionGroup.getModelObject();
	                    if (selectedOption != null) {
	                        if (Option.History.equals(selectedOption)) {
	                            filter.setHistory(textText
	                                    .getDefaultModelObjectAsString());
	                        } else if (Option.AuthorName.equals(selectedOption)) {
	                            filter.setAuthorName(textText
	                                    .getDefaultModelObjectAsString());
	                        } else if (Option.AuthorContact.equals(selectedOption)) {
	                            filter.setAuthorContact(textText
	                                    .getDefaultModelObjectAsString());
	                        } else if (Option.AuthorAffiliation
	                                .equals(selectedOption)) {
	                            filter.setAuthorAffiliation(textText
	                                    .getDefaultModelObjectAsString());
	                        } else if (Option.Title.equals(selectedOption)) {
	                            filter.setTitle(textText
	                                    .getDefaultModelObjectAsString());
	                        } else if (Option.Abstract.equals(selectedOption)) {
	                            filter.setAbstract(textText
	                                    .getDefaultModelObjectAsString());
	                        } else if (Option.PatientSpecies.equals(selectedOption)) {
	                            filter.setPatientSpecies(textText
	                                    .getDefaultModelObjectAsString());
	                        } else if (Option.Discussion.equals(selectedOption)) {
	                            filter.setDiscussion(textText
	                                    .getDefaultModelObjectAsString());
	                        }
	                    }
                    }

                    Component[] toUpdate = doSearch(filter);

                    if (toUpdate != null && target != null) {
                        for (Component c : toUpdate) {
                            target.addComponent(c);
                        }
                    }
                } catch (Throwable t) {
                    log.error("Searching for teaching-files failed!", t);
                }
            }

            @Override
            public void onError(AjaxRequestTarget target, Form<?> form) {
                BaseForm.addInvalidComponentsToAjaxRequestTarget(target, form);
            }

            @Override
            protected IAjaxCallDecorator getAjaxCallDecorator() {
            	if (decorator==null)
            	{
            		decorator = new TCMaskingAjaxDecorator(false, true);
            	}
            	return decorator;
            }
        };

        searchBtn.setOutputMarkupId(true);
        searchBtn
                .add(new Image("doSearchImg", ImageManager.IMAGE_COMMON_SEARCH)
                        .add(new ImageSizeBehaviour("vertical-align: middle;")));
        searchBtn.add(new Label("doSearchText", new ResourceModel(
                "tc.search.dosearch.text")).add(
                new AttributeModifier("style", true, new Model<String>(
                        "vertical-align: middle;"))).setOutputMarkupId(true));

        AjaxButton resetBtn = new AjaxButton("resetSearchBtn") {

            private static final long serialVersionUID = 1L;

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                TCQueryFilter filter = (TCQueryFilter) TCSearchPanel.this
                        .getDefaultModelObject();
                filter.clear();

                keywordInput.setValues();
                anatomyInput.setValues();
                pathologyInput.setValues();
                findingInput.setValues();
                diagnosisInput.setValues();
                diffDiagnosisInput.setValues();
                modalityChoice.setModelObject(null);
                levelChoice.setModelObject(null);
                patientSexChoice.setModelObject(null);
                categoryChoice.setModelObject(null);
                diagnosisConfirmedChoice.setModelObject(null);
                dateBox.setModelObject(null);
                textText.setModelObject(null);
                optionGroup.setModelObject(null);

                target.addComponent(form);
                target.appendJavascript("initUI($('#" + TCSearchPanel.this.getMarkupId(true) + "'));");
            }

            @Override
            public void onError(AjaxRequestTarget target, Form<?> form) {
                BaseForm.addInvalidComponentsToAjaxRequestTarget(target, form);
            }
        };
        resetBtn.add(new Image("resetSearchImg",
                ImageManager.IMAGE_COMMON_RESET).add(new ImageSizeBehaviour(
                "vertical-align: middle;")));
        resetBtn.add(new Label("resetSearchText", new ResourceModel(
                "tc.search.reset.text")).add(new AttributeModifier("style",
                true, new Model<String>("vertical-align: middle;"))));

        final WebMarkupContainer wmc = new WebMarkupContainer("advancedOptions");
        wmc.setOutputMarkupPlaceholderTag(true);
        wmc.setOutputMarkupId(true);
        wmc.setVisible(false);

        wmc.add(anatomyInput.getComponent());
        wmc.add(pathologyInput.getComponent());
        wmc.add(findingInput.getComponent());
        wmc.add(diagnosisInput.getComponent());
        wmc.add(diffDiagnosisInput.getComponent());
        wmc.add(modalityChoice);
        wmc.add(patientSexChoice);
        wmc.add(categoryChoice);
        wmc.add(levelChoice);
        wmc.add(diagnosisConfirmedChoice);
        wmc.add(dateBox);
        wmc.add(optionGroup);
        wmc.add(textText);
        wmc.add(resetBtn);

        final MarkupContainer advancedOptionsToggleLink = new AjaxFallbackLink<String>(
                "advancedOptionsToggle") {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick(AjaxRequestTarget target) {
                showAdvancedOptions = !showAdvancedOptions;

                wmc.setVisible(showAdvancedOptions);

                target.addComponent(wmc);
                target.addComponent(this);

                if (showAdvancedOptions)
                {
                    target.appendJavascript("initUI($('#" + wmc.getMarkupId(true) + "'));");
                }
            }
        }.add(new Label("advancedOptionsToggleText",
                new AbstractReadOnlyModel<String>() {
					private static final long serialVersionUID = -7928173606391768738L;
					@Override
                    public String getObject() {
                        return showAdvancedOptions ? getString("tc.search.advancedOptions.hide.Text")
                                : getString("tc.search.advancedOptions.show.Text");
                    }
                })).add(
                (new Image("advancedOptionsToggleImg",
                        new AbstractReadOnlyModel<ResourceReference>() {
                            private static final long serialVersionUID = 1L;

                            @Override
                            public ResourceReference getObject() {
                                return showAdvancedOptions ? ImageManager.IMAGE_COMMON_COLLAPSE
                                        : ImageManager.IMAGE_COMMON_EXPAND;
                            }
                        })).add(new ImageSizeBehaviour()));
        advancedOptionsToggleLink.setOutputMarkupId(true);

        final Form<?> form = new Form<Object>("searchForm");
        form.add(keywordInput.getComponent());
        form.add(wmc);
        form.add(searchBtn);
        form.setDefaultButton(searchBtn);
        form.setOutputMarkupPlaceholderTag(true);

        form.add(advancedOptionsToggleLink);

        add(dateSpanDialogOuterForm);
        add(form);

        add(new AjaxFallbackLink<Object>("searchToggle") {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick(AjaxRequestTarget target) {
                showSearch = !showSearch;

                form.setVisible(showSearch);

                target.addComponent(TCSearchPanel.this);

                if (showSearch)
                {
                	target.appendJavascript("initUI($('#" + TCSearchPanel.this.getMarkupId(true) + "'));");
                }
            }
        }.add((new Image("searchToggleImg",
                new AbstractReadOnlyModel<ResourceReference>() {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public ResourceReference getObject() {
                        return showSearch ? ImageManager.IMAGE_COMMON_COLLAPSE
                                : ImageManager.IMAGE_COMMON_EXPAND;
                    }
                })).add(new ImageSizeBehaviour())));
    }

    public void redoSearch(AjaxRequestTarget target)
    {
        redoSearch(target, null);
    }

    public void redoSearch(AjaxRequestTarget target, String iuid)
    {
        Component[] toUpdate = doSearch((TCQueryFilter)getDefaultModel().getObject());

        if (toUpdate != null && target != null) {
            for (Component c : toUpdate) {
                target.addComponent(c);
            }
        }
    }

    protected abstract Component[] doSearch(TCQueryFilter filter);

    private Object getFilterValue(TCQueryFilterKey key)
    {
        TCQueryFilter filter = (TCQueryFilter) getDefaultModelObject();
        return filter != null ? filter.getValue(key) : null;
    }

	private String getDateBoxInitUIJavascript(String markupId, DateSpanSearchItem dateSpanItem, boolean initUI) {
		StringBuilder js = new StringBuilder();
		if (initUI) {
			js.append("$('#").append(markupId).append("').combobox();");
		}
        js.append("if ($('#").append(markupId).append(" option:selected').text()==='").append(
        		dateSpanItem.getLabel(getSession().getLocale())).append("') {");
        js.append("$('#").append(markupId).append("').siblings('span').children('input').val('").append(
        		dateSpanItem.getFromUntilString(getSession().getLocale())).append("');");
        js.append("};");
        return js.toString();
	}

    public static interface IDateSearchItem extends Serializable {
    	String getId();
    	String getLabel(Locale locale);
    	Date getFromDate();
    	Date getUntilDate();
    }

    public static enum NotOlderThanSearchItem implements IDateSearchItem {
    	DAYS7(Calendar.DATE,-7), DAYS14(Calendar.DATE,-14),
    	MONTHS1(Calendar.MONTH,-1), MONTHS3(Calendar.MONTH,-3), MONTHS6(Calendar.MONTH,-6),
    	YEARS1(Calendar.YEAR,-1), YEARS5(Calendar.YEAR,-5), YEARS10(Calendar.YEAR,-10);
    	private static final transient Date now = new Date();
    	private transient Calendar cal = Calendar.getInstance();
    	private int calField;
    	private int amount;
    	private NotOlderThanSearchItem(int calField, int amount) {
    		this.calField = calField;
    		this.amount = amount;
    	}
    	public static NotOlderThanSearchItem valueForLabel(String label, Locale locale) {
    		for (NotOlderThanSearchItem item : values()) {
    			if (item.getLabel(locale).equals(label)) {
    				return item;
    			}
    		}
    		return null;
    	}
    	@Override
    	public String getId() {
    		return name();
    	}
    	@Override
    	public String getLabel(Locale locale) {
    		return toString();
    	}
    	@Override
    	public Date getFromDate() {
    		cal.setTime(now);
    		cal.add(calField, amount);
    		return cal.getTime();
    	}
    	@Override
    	public Date getUntilDate() {
    		return now;
    	}
    	@Override
    	public String toString() {
    		return TCUtilities.getLocalizedString("tc.search."+name().toLowerCase()+".text");
    	}
    }

    @SuppressWarnings("serial")
	public static class DateSpanSearchItem implements IDateSearchItem {
    	public static final String ID = "USER_DEFINED";
    	private Date now = new Date();
    	private Date fromDate = now;
    	private Date untilDate = now;
    	@Override
    	public Date getFromDate() {
    		return fromDate;
    	}
    	@Override
    	public Date getUntilDate() {
    		return untilDate;
    	}
    	@Override
    	public String getId() {
    		return ID;
    	}
    	@Override
    	public String getLabel(Locale locale) {
    		return TCUtilities.getLocalizedString("tc.search.datespan.text");
    	}
    	public void setFromDate(Date date) {
    		fromDate = date==null ? now : date;
    	}
    	public void setUntilDate(Date date) {
    		untilDate = date==null ? now : date;
    	}
    	public String getFromString() {
    		return dfDefault.format(fromDate);
    	}
    	public String getLocalizedFromString(Locale locale) {
			String lang = locale.getLanguage();
			if (Locale.GERMAN.getLanguage().equalsIgnoreCase(lang)) {
	    		return dfDE.format(fromDate);
			}
			else {
	    		return dfDefault.format(fromDate);
			}
    	}
    	public String getUntilString() {
    		return dfDefault.format(untilDate);
    	}
    	public String getLocalizedUntilString(Locale locale) {
			String lang = locale.getLanguage();
			if (Locale.GERMAN.getLanguage().equalsIgnoreCase(lang)) {
	    		return dfDE.format(untilDate);
			}
			else {
	    		return dfDefault.format(untilDate);
			}
    	}
    	public String getFromUntilString(Locale locale) {
			StringBuilder s = new StringBuilder();
			s.append(getLocalizedFromString(locale));
			s.append("-");
			s.append(getLocalizedUntilString(locale));
    		return s.toString();
    	}
    	@Override
    	public String toString() {
    		return getId();
    	}
    }

    @SuppressWarnings("serial")
	private class DateSpanDialog extends ModalWindow {
    	private DateSpanSearchItem item;
    	private DateSpanContentFragment fragment;
    	public DateSpanDialog(DateSpanSearchItem item)
    	{
    		super("date-input-dialog");
    		this.item = item;
    		setTitle(TCUtilities.getLocalizedString(
    				"tc.search.datespan.dialog.title"));
    		setInitialHeight(140);
    		setInitialWidth(350);
    		setContent(fragment =
    				new DateSpanContentFragment(getContentId()));
    	}

    	@Override
    	public void close(AjaxRequestTarget target) {
			item.setFromDate(fragment.getFromDate());
			item.setUntilDate(fragment.getUntilDate());
			super.close(target);
    	}

    	@Override
    	public void show(AjaxRequestTarget target) {
    		fragment.initDatePicker(target);
    		setTitle(TCUtilities.getLocalizedString(
    				"tc.search.datespan.dialog.title"));
    		super.show(target);
    	}

    	@Override
    	public String getCssClassName()
    	{
    		return super.getCssClassName() + " tc-dialog";
    	}

    	private class DateSpanContentFragment extends Fragment
    	{
			private DateConverter converter = new DateConverter() {
				@Override
				public DateFormat getDateFormat(Locale locale)
				{
					if (locale == null) {
						locale = Locale.getDefault();
					}

					String lang = locale.getLanguage();
					if (Locale.GERMAN.getLanguage().equalsIgnoreCase(lang)) {
			    		return dfDE;
					}

			    	return dfDefault;
				}
			};

    		private Model<Date> fromModel = new Model<Date>(item.getFromDate());
    		private Model<Date> untilModel = new Model<Date>(item.getUntilDate());

    		private TextField<Date> fromField = new TextField<Date>(
					"date-input-dialog-from-input", fromModel, Date.class) {
				@Override
				public IConverter getConverter(Class<?> type) {
					if (type!=null) {
						if (type.equals(Date.class)) {
							return converter;
						}
					}
					return super.getConverter(type);
				}
			};

    		private TextField<Date> untilField = new TextField<Date>(
					"date-input-dialog-until-input", untilModel, Date.class) {
				@Override
				public IConverter getConverter(Class<?> type) {
					if (type!=null) {
						if (type.equals(Date.class)) {
							return converter;
						}
					}
					return super.getConverter(type);
				}
			};

			public DateSpanContentFragment(final String id)
    		{
    			super(id, "date-input-dialog-content", TCSearchPanel.this);

    			fromField.setOutputMarkupId(true);
    			untilField.setOutputMarkupId(true);

    			Form<Void> form = new Form<Void>("date-input-dialog-inner-form");
    			form.setOutputMarkupId(true);
    			form.add(new Label("date-input-dialog-from-label", new Model<String>() {
    				public String getObject() {
    					return TCUtilities.getLocalizedString("tc.search.fromdate.text");
    				}
    			}));
    			form.add(fromField);
    			form.add(new Label("date-input-dialog-until-label", new Model<String>() {
    				public String getObject() {
    					return TCUtilities.getLocalizedString("tc.search.untildate.text");
    				}
    			}));
    			form.add(untilField);
    			form.add(new AjaxSubmitLink("date-input-dialog-ok-btn") {
						@Override
						public void onSubmit(AjaxRequestTarget target, Form<?> form)
	    				{
	    					close(target);
	    				}
	    			}
    				.add(new Label("date-input-dialog-ok-btn-text",
    						TCUtilities.getLocalizedString("tc.dialog.ok.text")))
    			);

    			add(form);

    			TCUtilities.addInitUIOnDomReadyJavascript(form);
    		}

			public Date getFromDate() {
				return fromModel.getObject();
			}

			public Date getUntilDate() {
				return untilModel.getObject();
			}

			public void initDatePicker(AjaxRequestTarget target) {
    			target.appendJavascript(getInitDatePickerJavascript(fromField.getMarkupId(true)));
    			target.appendJavascript(getInitDatePickerJavascript(untilField.getMarkupId(true)));
			}

			private String getDatePickerFormatOfCurrentLocale() {
				String lang = getSession().getLocale().getLanguage();
				if (Locale.GERMAN.getLanguage().equalsIgnoreCase(lang)) {
					return "dd.mm.yy";
				}
				else {
					return "mm/dd/yy";
				}
			}

			private String getDatePickerRegionOfCurrentLocale() {
				String lang = getSession().getLocale().getLanguage();
				if (Locale.GERMAN.getLanguage().equalsIgnoreCase(lang)) {
					return "de";
				}
				else {
					return "";
				}
			}

			private String getInitDatePickerJavascript(String markupId) {
    			StringBuilder js = new StringBuilder();
    			js.append("$('#").append(markupId).append("').datepicker(");
    			js.append("$.datepicker.regional['");
    			js.append(getDatePickerRegionOfCurrentLocale()).append("']);");
    			js.append("$('#").append(markupId).append("').datepicker('option', {");
    			js.append("showOn: 'button',");
    			js.append("buttonImageOnly: false,");
    			js.append("showOtherMonths: true,");
    			js.append("selectOtherMonths: true,");
    			js.append("showButtonPanel: true,");
    			js.append("changeMonth: true,");
    			js.append("changeYear: true,");
    			js.append("yearRange: '-20:+0',");
    			js.append("dateFormat: '").append(getDatePickerFormatOfCurrentLocale()).append("',");
    			js.append("})");
    			js.append(".next('button').text('').button({icons:{primary : 'ui-icon-calendar'}, text: false}).addClass('ui-combobox-toggle');");
    			js.append("$('#").append(markupId).append("').select('.hasDatePicker').removeClass('ui-corner-all').addClass('ui-corner-left');");
    			js.append("$('#").append(markupId).append("').select('.hasDatePicker').siblings('button').removeClass('ui-corner-all').addClass('ui-corner-right');");
    			return js.toString();
			}
    	}
    }
}


text:
package org.apache.wicket.markup.html.internal;

import java.util.regex.Pattern;

import org.apache.wicket.Component;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.mock.MockApplication;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.util.tester.WicketTestCase;
import org.junit.Test;

/**
 * Simple test using the WicketTester
 */
public class TogglePageTest extends WicketTestCase
{

	@Override
	protected WebApplication newApplication()
	{
		WebApplication webApplication = new MockApplication()
		{
			@Override
			protected void init()
			{
				super.init();
				getMarkupSettings().setStripWicketTags(true);
			}
		};
		return webApplication;
	}

	@Test
	public void testNoAjaxPage()
	{
		{
			// On
			FullReloadPage noAjaxPage = tester.startPage(FullReloadPage.class);
			assertVisible(noAjaxPage.getToggleable());
			tester.clickLink(noAjaxPage.getLink().getPageRelativePath());
		}
		{
			// Off
			FullReloadPage noAjaxPage = (FullReloadPage)tester.getLastRenderedPage();
			assertInvisible(noAjaxPage.getToggleable());
			tester.clickLink(noAjaxPage.getLink().getPageRelativePath());
		}
		{
			// On
			FullReloadPage noAjaxPage = (FullReloadPage)tester.getLastRenderedPage();
			assertVisible(noAjaxPage.getToggleable());
			tester.clickLink(noAjaxPage.getLink().getPageRelativePath());
		}
		{
			// Off
			FullReloadPage noAjaxPage = (FullReloadPage)tester.getLastRenderedPage();
			assertInvisible(noAjaxPage.getToggleable());
		}
	}

	@Test
	public void testTraditionalAjaxEnclosurePage()
	{
		{
			// On
			TraditionalEnclosureAjaxPage ajaxPage = tester.startPage(TraditionalEnclosureAjaxPage.class);
			assertVisible(ajaxPage.getToggleable());
			tester.clickLink(ajaxPage.getLink().getPageRelativePath(), true);
		}
		{
			// Off
			TraditionalEnclosureAjaxPage ajaxPage = (TraditionalEnclosureAjaxPage)tester.getLastRenderedPage();
			tester.assertComponentOnAjaxResponse(ajaxPage.getTraditionalAjaxVisibilityToggleRequiresPlaceholder());
			assertInvisible(ajaxPage.getToggleable());
			tester.clickLink(ajaxPage.getLink().getPageRelativePath(), true);
		}
		{
			// On
			TraditionalEnclosureAjaxPage ajaxPage = (TraditionalEnclosureAjaxPage)tester.getLastRenderedPage();
			tester.assertComponentOnAjaxResponse(ajaxPage.getTraditionalAjaxVisibilityToggleRequiresPlaceholder());
			assertVisible(ajaxPage.getToggleable());
			tester.clickLink(ajaxPage.getLink().getPageRelativePath(), true);
		}
		{
			// Off
			TraditionalEnclosureAjaxPage ajaxPage = (TraditionalEnclosureAjaxPage)tester.getLastRenderedPage();
			tester.assertComponentOnAjaxResponse(ajaxPage.getTraditionalAjaxVisibilityToggleRequiresPlaceholder());
			assertInvisible(ajaxPage.getToggleable());
		}
	}

	@Test
	public void testInlineEnclosureWithAdditionalAjaxTarget()
	{
		{
			// On
			InlineEnclosureWithAdditionalAjaxTargetPage ajaxPage = tester.startPage(InlineEnclosureWithAdditionalAjaxTargetPage.class);
			assertVisible(ajaxPage.getLabel1());
			assertVisible(ajaxPage.getLabel2());
			tester.clickLink(ajaxPage.getLink().getPageRelativePath(), true);
		}
		{
			// Off
			InlineEnclosureWithAdditionalAjaxTargetPage ajaxPage = (InlineEnclosureWithAdditionalAjaxTargetPage)tester.getLastRenderedPage();
			tester.assertComponentOnAjaxResponse(ajaxPage.getLabel2());
			assertInVisible(ajaxPage.getLabel1());
			assertInVisible(ajaxPage.getLabel2());
			tester.clickLink(ajaxPage.getLink().getPageRelativePath(), true);
		}
		{
			// On
			InlineEnclosureWithAdditionalAjaxTargetPage ajaxPage = (InlineEnclosureWithAdditionalAjaxTargetPage)tester.getLastRenderedPage();
			// WICKET-5302 - only the InlineEnclosure is in the Ajax response
			// Label1 is inside the InlineEncosure
			tester.assertComponentOnAjaxResponse("wicket_InlineEnclosure-0");
			tester.assertComponentOnAjaxResponse(ajaxPage.getLabel2());
			assertVisible(ajaxPage.getLabel1());
			assertVisible(ajaxPage.getLabel2());
			tester.clickLink(ajaxPage.getLink().getPageRelativePath(), true);
		}
		{
			// Off
			InlineEnclosureWithAdditionalAjaxTargetPage ajaxPage = (InlineEnclosureWithAdditionalAjaxTargetPage)tester.getLastRenderedPage();
			tester.assertComponentOnAjaxResponse(ajaxPage.getLabel2());
			assertInVisible(ajaxPage.getLabel1());
			assertInVisible(ajaxPage.getLabel2());
		}
	}

	@Test
	public void testInlineEnclosureAjaxPage()
	{
		String inlineEnclosureIdPrefix = "wicket__InlineEnclosure_";

		String inlineEnclosureHiddenPattern = "

";

		String inlineEnclosureVisiblePattern = "
";

		{
			// On
			InlineEnclosureAjaxPage ajaxPage = tester.startPage(InlineEnclosureAjaxPage.class);
			assertVisible(ajaxPage.getToggleable());
			tester.clickLink(ajaxPage.getLink().getPageRelativePath(), true);
		}
		{
			// Off
			InlineEnclosureAjaxPage ajaxPage = (InlineEnclosureAjaxPage)tester.getLastRenderedPage();
			tester.assertContains(inlineEnclosureHiddenPattern);
			assertInvisible(ajaxPage.getToggleable());
			tester.clickLink(ajaxPage.getLink().getPageRelativePath(), true);
		}
		{
			// On
			InlineEnclosureAjaxPage ajaxPage = (InlineEnclosureAjaxPage)tester.getLastRenderedPage();
			tester.assertContains(inlineEnclosureVisiblePattern);
			assertVisible(ajaxPage.getToggleable());
			tester.clickLink(ajaxPage.getLink().getPageRelativePath(), true);
		}
		{
			// Off
			InlineEnclosureAjaxPage ajaxPage = (InlineEnclosureAjaxPage)tester.getLastRenderedPage();
			tester.assertContains(inlineEnclosureHiddenPattern);
			assertInvisible(ajaxPage.getToggleable());
		}
	}

	private final String toggledText = "This button (and red border) should appear and disappear by pressing toggle";

	/**
	 * @param toggleable
	 */
	protected void assertInvisible(Component toggleable)
	{
		tester.assertInvisible(toggleable.getPageRelativePath());
		assertDoesNotContain(toggledText);
		assertDoesNotContain("Also this");
	}

	/**
	 * @param toggleable
	 */
	protected void assertVisible(Component toggleable)
	{
		tester.assertVisible(toggleable.getPageRelativePath());
		tester.assertContains(Pattern.quote(toggledText));
		tester.assertContains(Pattern.quote("Also this"));
	}

	/**
	 * @param label
	 */
	protected void assertVisible(Label label)
	{
		tester.assertVisible(label.getPageRelativePath());
		tester.assertContains(Pattern.quote(label.getInnermostModel().getObject().toString()));
	}

	/**
	 * @param label
	 */
	protected void assertInVisible(Label label)
	{
		tester.assertInvisible(label.getPageRelativePath());
	}

	/**
	 * @param string
	 */
	private void assertDoesNotContain(String string)
	{
		assertFalse("Should not contain: " + string,
			tester.getLastResponseAsString().contains(string));
	}

}


text:
namespace Owin.Scim.Repository.InMemory
{
    using System;
    using System.Collections.Generic;
    using System.Reflection;

    internal static class ObjectExtensions
    {
        private static readonly MethodInfo CloneMethod = typeof(Object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance);

        public static bool IsPrimitive(this Type type)
        {
            if (type == typeof(String)) return true;
            return (type.IsValueType & type.IsPrimitive);
        }

        public static Object Copy(this Object originalObject)
        {
            return InternalCopy(originalObject, new Dictionary<Object, Object>(new ReferenceEqualityComparer()));
        }
        private static Object InternalCopy(Object originalObject, IDictionary<Object, Object> visited)
        {
            if (originalObject == null) return null;
            var typeToReflect = originalObject.GetType();
            if (IsPrimitive(typeToReflect)) return originalObject;
            if (visited.ContainsKey(originalObject)) return visited[originalObject];
            if (typeof(Delegate).IsAssignableFrom(typeToReflect)) return null;
            var cloneObject = CloneMethod.Invoke(originalObject, null);
            if (typeToReflect.IsArray)
            {
                var arrayType = typeToReflect.GetElementType();
                if (IsPrimitive(arrayType) == false)
                {
                    Array clonedArray = (Array)cloneObject;
                    clonedArray.ForEach((array, indices) => array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices));
                }

            }
            visited.Add(originalObject, cloneObject);
            CopyFields(originalObject, visited, cloneObject, typeToReflect);
            RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect);
            return cloneObject;
        }

        private static void RecursiveCopyBaseTypePrivateFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect)
        {
            if (typeToReflect.BaseType != null)
            {
                RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType);
                CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate);
            }
        }

        private static void CopyFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy, Func<FieldInfo, bool> filter = null)
        {
            foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags))
            {
                if (filter != null && filter(fieldInfo) == false) continue;
                if (IsPrimitive(fieldInfo.FieldType)) continue;
                var originalFieldValue = fieldInfo.GetValue(originalObject);
                var clonedFieldValue = InternalCopy(originalFieldValue, visited);
                fieldInfo.SetValue(cloneObject, clonedFieldValue);
            }
        }
        public static T Copy<T>(this T original)
        {
            return (T)Copy((Object)original);
        }
    }
}


text:
Zerk is a JavaScript game engine developed by Kristoph Junge and [others](https://github.com/kristophjunge/zerk/graphs/contributors).

Zerk is based on an [Entity-Component-System](http://en.wikipedia.org/wiki/Entity_component_system) architecture.

Zerk aims to be able to run various types of 2D games on desktop and mobile devices.

More information can be found here [kristophjunge.com](https://kristophjunge.com).

**Other Software that Zerk is using:**

[Box2DWeb](http://code.google.com/p/box2dweb/) a JavaScript port of the [Box2D](http://box2d.org/) physics library written by Erin Catto and others. Used as the main physcis engine.

[JSON5](https://github.com/aseemk/json5) by Aseem Kishore and others. Used to to parse JSON files with comments.

[Poly-Decomp](https://github.com/schteppe/poly-decomp.js) a library for decomposition of polygons into convex regions writte by Stefan Hedman. Used to decompose complex polygons inside the entity editor.

[Node.js](https://nodejs.org/) by Joyent, Inc. and other Node contributors. Used to serve the zerk tool chain like the development server.

##Installation

Zerk can be installed via npm.

```bash
$ npm install -g zerk
```

##Using Zerk

Zerk is currently at an early development stage, use it at your own risk.

Navigate into an empty game directory and run:
```bash
$ zerk init
$ zerk dev
```

##License

Zerk is licensed under the MIT License.

##Documentation

The Zerk API documentation is available at [http://dev.kristophjunge.com/zerk/doc/latest](http://dev.kristophjunge.com/zerk/doc/latest)


text:
layout: post
title: "Unsecure High Risk Users"
date: "2017-05-02 13:12:43 +0200"
category: blog
link:
filename:
thumbnail:
---
Recently I stumbled upon a paper by John Scott-Railton from Citizen Lab
in which he discusses a study conducted by him with the help of the
university of Toronto focussing on the security of high risk users. To
be honest I was shocked after reading this document. This paper is worth
reading - as it points out the fundamental flaws we all have and how we
fail over and over again. First - what are high risk users in
Scott-Railtons [paper](https://www.computer.org/csdl/mags/sp/2016/02/msp2016020079.pdf)? He was focussing on civil rights activists, reporters and
people who are suffering from governmental prosecution.

As pointed out those guys were heavily target by phishing. A topic I have
been writing about a bit [[1](https://mmiedaner.github.io/phishing-explained/),[2](https://mmiedaner.github.io/feeding-the-phish-part-1),[3](https://mmiedaner.github.io/feed-the-phish-part-2/),[4](https://mmiedaner.github.io/feeding-the-phish-part-iii/)]. As pointed out by Scott-Railton the
social engineering part of most attacks is sophisticated compared to the
technical attacks. In his paper he shows various analysis of malware
families used with the phishing E-Mails. It is astonishing to see, that
no fancy trojan or zero days have been used. Most malware families have
been used over four to five years. This leads to the conclusion
that the technical expertise of the victims seems to be low and that
updating the system / patching is not done well.

This lack in technical skills seems to be covered partly by behavioural
measures. This means that instead of increasing the security of their
day to day use computers activists shifted to use file sharing services
like Google Docs instead of sending documents via E-Mail. This somehow
protects against phishing scams and malware - but it also puts the users
at risk, as Google still records a lot of data about them.

An other point Scott-Railton discusses at great length is the lack of
two factor authentication. In principle I agree with him. However I would
like to argue that if you do not have the time to patch - do you really
expect the use of multi factor authentication? The MFA concept is harder
to grasp and to use than patching.

This brings us to the final question - who is responsible? High risk
users can face dramatic consequences. However, as a provider of a
service platform your time is limited, so you can not secure it to the
last bit. Scott-Railton propose to enable multi factor authentication
by default. This could be an option - but you, as platform owner, still
need some motivation to enforce it on your users and maybe suffer
from the loss of customers. Yeah a bitter pill to swallow. If legislation
as proposed in the paper is really a good solution is up for discussion.
I do not agree on this point. There should be an other motivation. What do
you think?

Cheers !


text:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:id="@+id/rl_job"
                android:layout_width="wrap_content"
                android:layout_height="70dp"
                android:background="@color/white"
    >

    <com.woniukeji.jianguo.widget.CircleImageView
        android:id="@+id/user_head"
        android:layout_width="38dp"
        android:layout_height="38dp"
        android:layout_marginTop="14dp"
        android:layout_marginLeft="15dp"
        android:background="@drawable/button_background_login"
       />
<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_marginLeft="5dp"
    android:layout_toRightOf="@+id/user_head"
    android:orientation="vertical"
    >
    <TextView
        android:id="@+id/business_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15dp"
        android:layout_marginTop="18dp"
        android:text="凯宾斯基酒店宴会服务员"
        />
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="20dp"
        android:gravity="center"
        android:layout_marginTop="4dp"
        >

        <TextView
            android:id="@+id/tv_job_count"
            android:layout_marginLeft="4dp"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="月结"
            android:textSize="13dp"
            android:textColor="#9b9b9b"
            android:gravity="center"

            />
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="20dp"
        android:gravity="center"
        android:layout_marginTop="1dp"
        >

    </RelativeLayout>
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_marginBottom="2dp"
        android:layout_height="20dp"
        android:gravity="center"
        android:layout_marginTop="1dp"
        >

    </RelativeLayout>

</LinearLayout>

    <TextView
        android:id="@+id/tv_enroll_num"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignParentRight="true"
        android:text="18/25"
        android:layout_marginTop="10dp"
        android:layout_marginRight="18dp"
        android:textSize="10sp"
        android:gravity="center"
        android:visibility="gone"
        android:textColor="#f87c7c"
        />

    <TextView
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/gray_btn_bg_color"
        />
</RelativeLayout>


text:
/**
 * Gateway installs gateways
 * @alias Gateway
 * @memberOf core/boot/installers
 * @param {Object} gateways
 * @constructor
 *
 */
module.exports = function Gateway(gateways) {

	this.gateway = function(ext) {

		gateways.available.push(ext);

	};

};
module.exports.prototype = require('./PrototypeInstaller');


text:
@implementation User

- (void)encodeWithCoder:(NSCoder *)encoder {
    //Encode properties, other class variables, etc
    [encoder encodeObject:self.idUser forKey:@"idUser"];
    [encoder encodeObject:self.username forKey:@"username"];
    [encoder encodeObject:self.fullName forKey:@"fullName"];
    [encoder encodeObject:self.email forKey:@"email"];
    [encoder encodeObject:self.about forKey:@"about"];
    [encoder encodeObject:self.location forKey:@"location"];
    [encoder encodeObject:self.url forKey:@"url"];
    [encoder encodeObject:self.password forKey:@"password"];
    [encoder encodeObject:self.profileImage forKey:@"profileImage"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    if((self = [super init])) {
        self.idUser = [decoder decodeObjectForKey:@"idUser"];
        self.username = [decoder decodeObjectForKey:@"username"];
        self.fullName = [decoder decodeObjectForKey:@"fullName"];
        self.email = [decoder decodeObjectForKey:@"email"];
        self.about = [decoder decodeObjectForKey:@"about"];
        self.location = [decoder decodeObjectForKey:@"location"];
        self.url = [decoder decodeObjectForKey:@"url"];
        self.password = [decoder decodeObjectForKey:@"password"];
        self.profileImage = [decoder decodeObjectForKey:@"profileImage"];
    }
    return self;
}

@end