GWT is Flexible — an iPhone Demo

GWT is a very flexible environment that allows you to write a web application in Java and compile it to Javascript — even for the iPhone.

A number of people have fears with GWT, for instance

  • (not true) GWT isn’t flexible which will lead developers down a dead-end path.
  • (not true) GWT is ugly, and can’t be used to make “gucci” UIs.

This post will show that these are just myths.

Demos

First, lets take a look at the demo.  Below is a re-write of Apple’s “Simple Browser” demo using GWT.  You can find the original demo here: https://developer.apple.com/webapps/docs/referencelibrary/index-date.html (search on the page for “simple browser”).

You can try the GWT version of the demo on the iPhone: live GWT demo, and the source code which includes the source control history.

or compare it to the original Apple demo

For those who don’t have an iPhone, here is a quick video of the demo written in GWT:

GWT is Flexible

The iPhone provides several unique challenges to GWT:

  • iPhone has specific events like orientation change, touch, and transition end events
  • iPhone has specific animation features to slide from one “page” to the next (Page, in the demo, is conceptual.  Once the app is loaded, it never goes to another HTML page.)
  • The built-in GWT controls prefer tags like <div> and <table>.  We want to use other HTML tags such as <ul> and <li> in the iPhone

GWT manages events, with good reason. By managing events, GWT prevents a whole class of memory leaks. So implementing events that GWT is unaware of is not ideal. The demo handles this by either firing event on objects that will always exist in the application, or adding or remove events when the control is added or removed from the DOM using the onLoad() and onUnload() methods.

The GWT demo wires up the iPhone specific events by calling native JSNI method. In native methods you write any Javascript you want, but you have the added risk of memory leaks. This method wires up the screen orientation change event:

	private native void registerOrientationChangedHandler(
			OrientationChangedDomEvent handler) /*-{
		var callback = function(){
			handler.@net.lenharts.gwt.sampleiphoneapp.client.model.Screen$OrientationChangedDomEvent::onOrientationChanged()();
		}

		$wnd.addEventListener("orientationchange", callback, false);
	}-*/;

When the screen orientation changes, the handler.@net.lenharts.gwt.sampleiphoneapp.client.model.Screen$OrientationChangedDomEvent::onOrientationChanged()() method is called, which is a special GWT notation allow you to call Java methods from Javascript. When the code is compiled to Javascript, this will be replaced with the actual compiled Javascript function.

Animations on the iPhone are surprising easy. In fact animations are included in the CSS 3 specification soon to be released. If you have the Google Chrome 2 browser, you can try out the animations in the link.

To use these animations the pseudo code is

  1. Set the content of a element.
  2. Set the element to a CSS class that disables animations
  3. Set the element to another CSS class that will position the element at the beginning position of the animation (give the element two classes)
  4. Schedule a DeferredCommand
  5. In the DeferredCommand, remove the CSS classes set above and set the element to a CSS class that enables animations.
  6. Then set the element to a CSS class to position the element at the destination position. (again keeping the animation class).
  7. When the transition ends (using the transitionend event), disable animations by removing the CSS class that enables animations and replace it with the CSS class to disable animations.

GWT allows you to create any type of element within the <body> tag. The default set of widgets, unfortunately, do not give you every tag, so you have to write your own class. Luckily you only need two classes to create any element: one class for elements that contain text, and one class for elements that contain other elements.

Here is the class that contains other elements:

package net.lenharts.gwt.sampleiphoneapp.client.util;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.*;

public class GenericContainerTag extends ComplexPanel {
	public GenericContainerTag(String tagName) {
		setElement(DOM.createElement(tagName));
	}

	/**
	 * Adds a new child widget to the panel.
	 * 
	 * @param w
	 *            the widget to be added
	 */
	@Override
	public void add(Widget w) {
		add(w, getElement());
	}

	/**
	 * Inserts a widget before the specified index.
	 * 
	 * @param w
	 *            the widget to be inserted
	 * @param beforeIndex
	 *            the index before which it will be inserted
	 * @throws IndexOutOfBoundsException
	 *             if <code>beforeIndex</code> is out of range
	 */
	public void insert(Widget w, int beforeIndex) {
		insert(w, getElement(), beforeIndex, true);
	}
}

To create the element, you pass in the name of the tag. For instance, if you want to create a <ul> tag, you create it like so

GenericContainerTag ul = new GenericContainerTag("ul");

The class for elements that contain text is a bit more complicated, especially since we’re enabling iPhone specific events here. If you were to take out the event code, you’d find this to be much smaller. Plus it tries to wire touch events for the iPhone, and click events for all other browsers. For now, don’t worry about the details, let’s just skip down to how to create it.

package net.lenharts.gwt.sampleiphoneapp.client.util;

//based on Label.java source code that comes with GWT

import com.google.gwt.user.client.ui.*;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;

public class GenericTextTag<E> extends Widget implements HasText {

	private boolean mMovedAfterTouch = false;
	private E mAttachedInfo;

	private boolean mWantsEvents = false;
	private boolean mEventsWiredUp = false;
	HandlerRegistration mHandlerRegistration;

	public GenericTextTag(String tagName) {
		setElement(Document.get().createElement(tagName));
	}

	@Override
	protected void onLoad() {
		if (mWantsEvents) {
			wireUpEvents();
		}
	}

	private void wireUpEvents() {
		if (!mEventsWiredUp && this.isAttached()) {
			if (hasTouchEvent(this.getElement())) {
				registerDomTouchEvents();
			} else {
				// used for debugging:
				mHandlerRegistration = this.addDomHandler(new ClickHandler() {
					@Override
					public void onClick(ClickEvent event) {
						event.preventDefault();
						fireTouchClick();
					}
				}, ClickEvent.getType());
			}
			mEventsWiredUp = true;
		}
	}

	private void wireDownEvents() {
		if (mEventsWiredUp) {
			if (hasTouchEvent(this.getElement())) {
				unRegisterDomTouchEvents();
			} else {
				mHandlerRegistration.removeHandler();
			}
		}
		mEventsWiredUp = false;
	}

	@Override
	protected void onUnload() {
		wireDownEvents();
	}

	public GenericTextTag(String tagName, String text) {
		this(tagName);
		setText(text);
	}

	public void setAttachedInfo(E info) {
		mAttachedInfo = info;
	}

	public final HandlerRegistration addHandler(
			final TouchClickEvent.TouchClickHandler<E> handler) {
		if (!mWantsEvents) {
			mWantsEvents = true;
			wireUpEvents();
		}
		return this
				.addHandler(
						handler,
						(GwtEvent.Type<TouchClickEvent.TouchClickHandler<E>>) TouchClickEvent
								.getType());
	}

	public E getAttachedInfo() {
		return mAttachedInfo;
	}

	private native void registerDomTouchEvents() /*-{
		var instance = this;
		var element = this.@net.lenharts.gwt.sampleiphoneapp.client.util.GenericTextTag::getElement()();

		element.ontouchstart = function(e){
				instance.@net.lenharts.gwt.sampleiphoneapp.client.util.GenericTextTag::onDomTouchStart()();
		};

		element.ontouchmove = function(e){
				instance.@net.lenharts.gwt.sampleiphoneapp.client.util.GenericTextTag::onDomTouchMove()();
		};

		element.ontouchend = function(e){
				instance.@net.lenharts.gwt.sampleiphoneapp.client.util.GenericTextTag::onDomTouchEnd()();
		};
	}-*/;

	private native void unRegisterDomTouchEvents() /*-{
		var instance = this;
		var element = this.@net.lenharts.gwt.sampleiphoneapp.client.util.GenericTextTag::getElement()();

		element.ontouchstart = null;

		element.ontouchmove = null;

		element.ontouchend = null;
	}-*/;

	public void onDomTouchStart() {
		mMovedAfterTouch = false;
	}

	public void onDomTouchMove() {
		mMovedAfterTouch = true;
	}

	public void onDomTouchEnd() {
		if (mMovedAfterTouch) {
			return;
		}

		fireTouchClick();
	}

	private void fireTouchClick() {
		fireEvent(new TouchClickEvent<E>(this));
	}

	public String getText() {
		return getElement().getInnerText();
	}

	public void setText(String text) {
		getElement().setInnerText(text);
	}

	private static native boolean hasTouchEvent(Element e) /*-{
		var ua = navigator.userAgent.toLowerCase();

		if (ua.indexOf("safari") != -1 &&
			ua.indexOf("applewebkit") != -1 &&
			ua.indexOf("mobile") != -1) 
		{    	
			return true;
		}
		else 
		{
			return false;
		}
	}-*/;

}

The code below creates an <li> tag that contains the text “Hello World!”. The “Hello World!” test is not fixed. The class has getter and setter methods for changing the text too.

GenericTextTag<String> li = new GenericTextTag<String>("li", "Hello World!");

GWT Does Not Have to be Ugly

As you can see in the examples above, you can create any HTML tag, and you can use any CSS style you like. The sky is the limit on how you style your GWT application. Many people see the GWT examples and they have an “application” feel to it. Granted the built-in widgets encourage this, but as you can see, you are not restricted to their widgets and you can have a more “document” feel to your webpage. You have complete control of the body tag.

Why GWT?

For me, the difference between GWT and Javascript is whether you want to work with a static language like Java, or a dynamic language like Javascript.  I assert, with little proof, that static languages are better.  They provide a much deeper verification of your code which I feel is necessary of any sizable application.  I remember the VBScript days, and I don’t want to return to shipping bugs that are trival to find by a static language compiler.

There are issues with the size of the javascript download that both sides claim to be better.

  • Pure Javascript is smaller because you include a library from Google that the user has already downloaded plus your small javascript code that you write
  • GWT is smaller, because the GWT compiler is highly optimized to remove dead code and to restructure your code to be as small as possible.  For instance, if you only use 10% of a library, then the downloaded code includes only 10% of the library.

Small apps can work OK with a dynamic language, with the potential that it will have less code to download.  However for larger applications, the GWT compiler will produce smaller code as compared to hand written, minified Javascript and the static language will help reduce the number of bugs.

About Clay Lenhart

I am a DBA/Technical Architect for Latitude Group and love technology.
This entry was posted in Languages and tagged , , . Bookmark the permalink.

44 Responses to GWT is Flexible — an iPhone Demo

  1. This was a very interesting article. I haven’t seen any discussion of GWT applications and iPhone. Did you try extending any of the GWT controls to add these events?

  2. Clay Lenhart says:

    Oh yes. :) The source code is there to see how the events are wired up. Unfortunately you can’t wire the events in a GWT way, but since you can code Javascript in GWT, you can wire the iPhone events.

  3. Bruce Johnson says:

    Nice article & insight.

  4. OtengiM says:

    This is great article, It smells as a new GWT Iphone framework comming up?!. It would be kick ass to have a full stack from back end with google guice and webservice to the front end with GWT for iphone web applications with your ideas.

  5. devdanke says:

    Thank you for showing how to do this and linking to the demo. I’ve wanted to write a GWT iPhone app for a while, but didn’t know how hard it would be. You’ve shown me that it’s doable.

  6. domanthan says:

    in fact, we need only the GWT Rpc Compiler for Iphone, isnt it? Cause iphone doesnt need HTML and Javascripts

  7. Bart Guijt says:

    Looks like you beat me to it :-)

    Anyway, interesting research you did here. I am about to do mostly the same thing: incorporate the Dashcode parts into GWT – see http://code.google.com/p/gwt-mobile-webkit/

    Cheers!

  8. Clay Lenhart says:

    Bart,

    I saw that site recently! Great work!

  9. Erick Audet says:

    I agree with the above comment about the smell of a new GWT/iPhone framework. This is great source code. I have tested your source code by adding some new tags in the xml files (listitems, buttons, textbox) and it works great. Perhaps an opensource project should be created.

  10. Clay Lenhart says:

    No, there are too many “gotchas” for this to be a framework. For example, you have to be careful with the way I did iphone events in this example — you could get a memory leak. I couldn’t hook in to the GWT way of doing event unfortunately.

    This will remain what it is — an example. Feel free to use it as a reference!

  11. Nico says:

    Hello !

    You did a great job !…. but the sources and demo are no more available (I already saw them a few weeks ago). Do you plan to publish them back ?

    Thx, Nico

  12. Clay Lenhart says:

    Whoops, these got lost in the upgrade. You can find the source code here as well: http://bitbucket.org/Clay/sampleiphonewebapp

  13. Nico says:

    Thx ! It will be useful to test it on Android.

  14. Clay Lenhart says:

    The source files are back again.

  15. Geotako says:

    Thanks to this example, we have developed a GPS App for iPhone/Android with 100% Google Technologies (m.geotako.com):

    Technical Info:
    – Back-end using Google AppEngine cloud infrastructure
    – Front-end using Google Web Toolkit which can run on both iPhone Safari and Android Chrome (also other desktop browsers)
    – GWT based internationalization
    – Integrated with Facebook Connect for wall posting
    – Using Google Maps API for reverse geocoding (retrieve your address automatically when you add a new location)
    – HTML5 based Geolocation for tracking your location with GPS
    – HTML5 based Web Database for storing local information in the browser

    Features:
    – Discover interesting locations around you with beautiful photos
    – Share your journey with friends by checking-in to locations around you
    – Grabbing mayorship of a location when you checkin frequently
    – Post to Facebook wall when you checkin
    – Locate where your friends have been to
    – Add new locations with photos
    – A ranking showing the top travelers with the highest number of mayorships
    – Support English, Traditional Chinese and Simplified Chinese

    You may try it here: m.geotako.com

    The app can also be found in Google App Engine Applications Gallery

  16. I think other web site proprietors should take this website as an model – very clean and fantastic style and design, in addition to the content. You are an expert in this topic!

  17. Isaac Fraser says:

    If your cat is outside and happens to brush up against a leaf or branch, that’s the place the ticks like to stay. After you have removed a tick from your dog, it is very important that you observe your pet for several weeks. The mice will be unaffected by the treated cotton and will be relieved of their unwanted guests as well.

  18. Thanks for some other informative blog. Where else may just I am getting that kind of info written in such an ideal approach? I have a challenge that I’m simply now working on, and I have been on the glance out for such information.

  19. If you desire to grow your experience just keep visiting this web page and be updated with the latest information posted here.

  20. Frank Reid says:

    Asking questions are in fact nice thing if you are not understanding anything fully, except this piece of writing offers pleasant understanding even.

  21. Mary Kelly says:

    Absolute beneficial suggestions you have stated, thanks a lot for writing.

  22. Megan Ince says:

    you’re actually a good webmaster. The web site loading velocity is amazing. It seems that you’re doing any distinctive trick. Moreover, The contents are masterpiece. you’ve done a magnificent task in this topic!

  23. Hannah Black says:

    Aw, this was a very nice post. Taking a few minutes and actual effort to create a top notch article… but what can I say… I hesitate a whole llot and never manage to get anything done.

  24. My spouse and i ended up being comfortable when John managed to do his studies because of the precious recommendations he made while using the site. It’s not at all simplistic to simply always be giving out techniques which often the others might have been making money from. So we already know we now have the writer to thank for that. The illustrations you made, the simple web site menu, the relationships you will assist to instill it is most overwhelming, and it is helping our son and the family know that this article is thrilling, which is certainly incredibly mandatory. Thank you for all!

  25. I have been examinating out many of your articles and i can state pretty nice stuff. I will make sure to bookmark your website.

  26. At this time it seems like BlogEngine is the preferred blogging platform out there right now. (from what I’ve read) Is that what you are using on your blog?

  27. Pretty great post. I simply stumbled upon your weblog and wanted to mention that I have really loved surfing around your blog posts. In any case I will be subscribing for your rss feed and I hope you write again very soon!

  28. security says:

    Hi, thanks for brining up the new Ubuntu release. IT is one of the best releases and i have it installed on my rig at home. the only issue is buggy ati driver.

  29. ブランドN級品ロレックススーパーコピーのメンズレディースユニセックス時計通販専門店,ロレックス 時計コピー豊富に揃えております,当店は本物と区分けが付かないようなN級品ロレックスコピーを扱っております,ロレックス偽物激安,2年品質保証,送料無料。偽物ブラン日本最大級の最高のスーパーコピーブランド財布激安代引き販売店,スーパーコピー時計の激安老舗.!国内外No.1時計コピー工房,アフターサービスも自ら製造したスーパーコピー時計なので、技術力でお客様に安心のサポー トをご提供させて頂きます。スーパーコピー代引きN品をご 購入の方は、こちらへ.弊社は正規品と同等品質のコピー品を低価でお客様に提供します!すべての商品は品質2年無料保証です http://www.wtobrand.com/prada-bag1.html

  30. 著名なシャネルコピーの新作が発売中著名なシャネルコピーの大人気なバッグや財布などの新作が情報満載で、高級感が溢れる逸品はこちらで超低価格で購入できます。いっぱい書類もあれば、品質にも保証があります。こちらはお洒落さを追求するのあなたの最高な選びです。 http://www.brandiwc.com/brand-super-15-copy-0.html

  31. 日本超人気のスーパーコピーブランド激安通販専門店!┏━━━━━2016年人気最高品質━━━━━┓ ◎━ 腕時計、バッグ、財布、アクセサリ ━◎最新入荷!主に販売商品:ロレックスコピー、カルティエコピー、エルメスコピー、ブラダコピー、ルイヴィトンコピー、シャネルコピー、グッチコピー等一流のブランドコピー品。商品の数量は多い、品質はよい、高品質のブランドコピーを超激安な価格で販売しています。信用第一、商品は絶対の自信が御座います!驚きと満足を保証致します。ぜひご来店くださいませ!★ 2016年注文割引開催中,全部の商品割引10% ★ 在庫情報随時更新! ★ 実物写真、付属品を完備する。 ★ 100%品質を保証する。 ★ 送料は無料です(日本全国)!★ 経営方針: 品質を重視、納期も厳守、信用第一!税関の没収する商品は再度無料にして発送します! http://www.wtobrand.com/sbfr4.html

  32. スーパーコピーブランド業界最高級品質のスーパーコピー通販専門店最大の腕時計ブライトリングの作りはベントレー・コレクションのためのbrietling。あなたが私の仕事をよく知っているならば、あなたは私の大時計が好きです、しかし、それらの腕時計の多くは、ちょうど私のためにあまりに大きいのを知っています。あなたが本当にそれらからのいくつかを引き出すために世界最大のリストの男性の1人である必要があります。この新しい腕時計の広いより狭い42ミリメートルである。それは非常に広いラグ構造による大きな実は着るでしょう。バルナートコレクションの中で、この新しい42ミリメートルサイズの私の意見では喜ばしい追加です。 http://www.ooowatch.com/tokei/chopard/index.html

  33. スイス独立時計職人ブランドSPEAKE-MARIN創始者ピーターSpeake-Marinさんが手を携えてヨーロッパ坊グループは、一貫して優雅な紳士の姿には上海に到着し、初めて出展2012年バーゼル表展が発表した最新作は、新しいSerpent Calendar。 http://www.ooobrand.com/distribution/index.html

  34. ティソは、スイスのイータunitas 6497手動巻き機械的運動として始まった。この運動は、しばしば選ばれるとき、白骨化はそれがすべてどのように働くのを見る多くのその内臓を掻き出すように本当にできました。それさえ巧みに白骨化したと刻まれたときは非常に美しく見えます基本的な運動を助けます。どんなティソここでしました。完全に白骨化した腕時計を提供します、しかし、1つのことをまだ読みやすいです。部分のダイヤルの詳細は以下の機転で時間と分の指標の全てを持つことになる。ロレックス スーパーコピー ブラックまたはシルバーダイヤルと来て、ティソのスポーティ・ローマ数字としては、24時間の時間分のフルスケールを使用しています。ダイヤルに切って、さかさまのキノコに似ている。この窓は時間に干渉しない、そして、あなたは右に移動します。 http://www.newkakaku.com/lab12.htm

  35. パテック・フィリップスーパーコピー当店設立以来、世界的に有名なブランドコピー品を扱っており、各商品の完成度が非常にいいです。鮮明な商品の写真、商品紹介および規格まで詳しく掲示しております。当店の商品は正規品に対して1:1の完成度で造られています。当店では信用第一を基に、出荷した商品に対して品質と確実にお届けできることを保障しています。ご注文頂いた場合、送料は当店でご負担させて頂きます。ぜひご利用頂き、買い物をお楽しみにしてください http://www.msnbrand.com/goods-copy-4781.html

  36. 何をあなたが感じる中国の腕時計について。人に聞く」が中国で作られるのを見て、「それが何であるかを心に浮かんでくるのですか?それはたぶん両方の正と負のものの組み合わせである。 カルティエ 時計コピー 私は、ほとんどの人々のいずれかを安価に大量生産された腕時計のことを考えると思います、または偽の贅沢品。を含んで、まだ中国の出てくる商品の正確な記述。 http://www.wtobrand.com/sbfr4.html

  37. ダイヤルは靑銅、魅惑的な色合いと、テクスチャ、そこからのイメージ、それは判断「鮭盤”として、我々は見ている他のブランド。しかし更に–、の設計元素シールの任務はかなり一部のダイヤル時間。これは、原則としては、この二つのfilliouオンの仕事、私と謝罪、もし私のあれらの熟知して更に彼のキャリアを発見して私の理解はまったく正しい。 http://www.wtobrand.com/pr1.html

  38. ガガミラノ スーパーコピー 設計の観点から見ると、あなたが話して易通は中から、好易通の頭蓋骨を思ったのは宇宙全体の漫画、アニメや映画の頭蓋骨と人物。私は選んで他人のスカル、T-1000ターミネーター、もちろん、罰者の頭蓋骨マーク。その決定させて好易通の頭蓋骨の時計はもちろん彼ら自分の連想と骨の好易通頭骨時計ダイヤル彼らに注意。私から見れば、好易通として未来のスカルスタイルと見てあの奇跡のアイアンマン見副;意味ドクロはドクロと多くの「悪いassery」頭蓋骨、マスクや鎧。 http://www.newkakaku.com/cb11.htm

  39. Q計画の中心要素は、オーデマピゲ時計工場が司会のQ国際賞授与対象は保護児童権益側は重大な貢献の有名人や社会機構。新しいMillenaryミレニアムクインシージョーンズ腕時計の一部販売収入はクインシージョーンズ基金会に寄付する。オーデマピゲ表グループCEOの莫菲利(フィリップ・Merk)さんは「クインシージョーンズは天才芸術家、プロデューサー、さらにはまず1位の人は広い心を持っている。ブルガリ偽物彼はいろいろな困難を克服して育成の偉大な事業に感動し、彼の高貴な品質は恐れ入っ、私たちに人生の中の重要な一課は、完璧な芸芸術」と情熱、同様の哲学はこの伝奇音楽人とオーデマピゲ表ほど係がきつい。オーデマピゲ135年通りで休まないの努力の成果を壮大タブ史、クインシージョーンズも数十年一日のように待ってた世界の流行音楽史をつくる。MILLENARYミレニアムクインシージョーンズ(Quincyジョーンズ新しい)限定時計演繹ミレニアム横楕円形のケースにこの素晴らしいミュージシャンを演じるその特色に富んだオーデマピゲ新しい現代Millenaryミレニアムシリーズの特徴をマークし、黒鋼の個性豊かな横楕円形のケース。表面のようなケースは多分霧中間部分面研磨磨き;別のいくつかの表面表圏や表耳正面は多分亮面研磨に磨きをかけて、令其のレイヤー感のほかヘルニア。スーパーコピーケースデザイン精細には縦横に霧面研磨磨きをセイコー飾り。亮面バフ磨きのキャップを刻んでクインシージョーンズと署名のMillenary Quincyジョーンズ–リミテッドEdition文字が、貴重な表項で世界限定500発行。ミレニアムクインシージョーンズ腕時計配備黒革バンド、組み合わせとケースの呼応を黒鋼APと折り畳み表ボタン。ミレニアムクインシージョーンズ腕時計を踏襲して2000シリーズ特有のオフセット文字盤も目利き一目で見分けるその係のマーク名門の出。文字盤外縁描き出して繊細なアウトコース、美しい黒の表面に向けては小が大のプラチナローマ数字に標を連想させるニューヨークジャズクラブで徹夜の音楽演奏。ブランドコピーミレニアムクインシージョーンズ腕時計黒を基調とし、その豊富な深さのレベルを作成するために運用出動人心の琴線の対比、工夫をこらした鍵盤柄飾りをめぐる時表示文字盤、生き生きとした鍵盤弾くよう現場ジャズのリズムがありありと表面の上に、軽快。 http://www.bestevance.com/rolex/daytona/index.htm

  40. Thanks very useful. Will certainly share website with my friends. http://bit.ly/2f0xJ92

  41. Absolutely composed content material, thank you for information. “Necessity is the mother of taking chances.” by Mark Twain.

  42. Thanks really beneficial. Will share site with my friends.|

  43. ルイヴィトン財布
    弊店では信用第一主義を徹底しており社員全員下記の方針のもとに頑張っています。
    1.不適合品を入荷しない。
    厳しく受け入れ検査を行い、お客様に満足いただける品質のいい物だけを入荷する。
    2.不適合品を出荷しない。
    出荷前に細部まで二重確認を行い、お客様からご注文頂いた商品を納期通り出荷する。
    3.お客様からのクレームゼロ
    お客様第一主義を徹底し、お客様からのお問い合わせ、苦情等に対して積極的かつ丁寧に対応いたします。

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>