atelier:mitsuba

i love UI/UX, Blend, XAML, Behavior, P5, oF, Web, Tangible Bits and Physical computing. なにかあればお気軽にご連絡ください。atelier@c-mitsuba.com

WebViewのInvokeScriptでほげって作るWindows Store Apps

まくどくーぽんの作り方です。
すとあにも公開されたので、作り方をご紹介。(ただしデザイン、UI、レイアウト除く)
いやまぁなんでこんなことをかくかというと、UIはxamlで書きたいけど、あたしC#わかんないし、
そもそもうぇぶやさんだけど、htmlだるいし、、、、ってかんじ。

1.まず、前振り
マクドクーポンのページはこんなん
http://www.mcdonalds.co.jp/sales/new/smileplus/index.php
ヘッダーにはこんなのが書かれています。

<head>
<meta http-equiv="content-type" content="text/html; charset=Shift_JIS">
<meta http-equiv="content-style-type" content="text/css">
<meta http-equiv="content-script-type" content="text/javascript">
<meta name="description" content="日本マクドナルドの新商品をはじめ、朝マックなど全商品を紹介するコーナー! さらに、お得なプロモーションなども紹介しています。必ずチェックしてね!">
<meta name="keywords" content="mcdonaldsweb,ハンバーガー,ビッグマック,ポテト,クーポン,QRコード,バリューセット,ハッピーセット、朝マック,100円マック">
<meta property="og:image" content="http://www.mcdonalds.co.jp/campaign/common/graphic_files/og_image/thumbnail_01.jpg">
<title>クーポンダウンロード | クーポン | McDonald's Japan</title>
<link rel="stylesheet" type="text/css" href="/common/stylesheet_files/common.css">
<link rel="stylesheet" type="text/css" href="/sales/new/smileplus/stylesheet/index.css">
<script id="facebook-jssdk" src="//connect.facebook.net/ja_JP/all.js#xfbml=1"></script><script id="twitter-wjs" src="//platform.twitter.com/widgets.js"></script><script src="https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.ja.vr1k5xso8CI.O/m=plusone/am=AQ/rt=j/d=1/rs=AItRSTO9DceUEVkDFFZ4qbY_GxnUsGuP4A/cb=gapi.loaded_0" async=""></script><script type="text/javascript" async="" src="https://apis.google.com/js/plusone.js" gapi_processed="true"></script><script type="text/javascript" src="/common/script_files/jquery.js"></script>
<script type="text/javascript" src="/common/script_files/common.js"></script><script type="text/javascript" src="http://www.mcdonalds.co.jp/shared/script/swfobject.js"></script><script type="text/javascript">  window.___gcfg = {lang: 'ja'};  (function() {    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;    po.src = 'https://apis.google.com/js/plusone.js';    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);  })();</script>
<!-- [old] -->
<!--- for legacy browser --->
<link rel="stylesheet" href="/base_css/layout.css" type="text/css">
<style type="text/css">
<!--
.std{font-size: 10pt; line-height: 1.4em;}
.std11{font-size: 11pt; line-height: 1.4em;}
em{font-style: normal; font-weight: bold;}
.price{font-size: 11pt;}
.std11Copy { font-size: 11pt; line-height: 1.4em; ; text-decoration: underline}
.stds {font-size: 9pt}
-->
</style>
<script type="text/javascript" src="/base_js/window.js"></script>
<script language="JavaScript">
<!--
function checkbox_changer(flg,no){
	before0=0;before1=0;before2=0;after2=1;before3=2;after3=5;before4=6;after4=15;before5=16;after5=17;

	if(flg == "true"){
		check_true(eval("before"+no),eval("after"+no));
	}else{
		check_false(eval("before"+no),eval("after"+no));
	}
}

function check_true(before, after){
	var chk=0;
	for (i=0 ; i < document.forms[1].elements["coupon[]"].length; i++){
		if((before=="0") && (after=="0")){
			document.forms[1].elements["coupon[]"][i].checked = true;
		}else if((before <= i) && (after >= i)){
			document.forms[1].elements["coupon[]"][i].checked = true;
		}
	}
	return false;
}

function checkCouponCount(cnt){
	flg = "false";
	for(i=0;i<=cnt;i++){
		if(document.forms[1].elements["coupon[]"][i].checked) flg = "true";
	}
	if(flg == "false"){
		window.alert('クーポンをチェックしてください。');
		return false;
	}else{
		return true;
	}
}

function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}
//-->
</script>
<!-- /[old] -->
<meta name="viewport" content="width=997px">
<style type="text/css">省略</style>
</head>

長いんですが、大事なのはここです。

<script type="text/javascript" src="/common/script_files/jquery.js"></script>

つぎにクーポンのフォームの1部分を見てみましょう。

<tr bgcolor="#ffffff"><td width="21" align="left" class="std"><input type="checkbox" name="coupon[]" value="248"></td><td width="340" align="left" class="std"><em><font color="#ff0000">ダブルチーズバーガー</font></em></td><td width="120" align="right" class="std"><em><font color="#ff0000"><span class="price">\170</span></font></em></td></tr>

のここ

<input type="checkbox" name="coupon[]" value="248">

どうやらダブルチーズバーガーのvalue="248"ですね。
で、だぶるチーズバーカークーポンのURLはっというと
http://img.mcdonalds.co.jp/sales/new/smileplus/img/coupon/coupon248.gif だそうです。

ふむ。。つまり。。。
http://img.mcdonalds.co.jp/sales/new/smileplus/img/coupon/coupon + value + .gif
ですね、ということはhtmlのとこから、valueだけ引っこ抜けばいいんですが、正規表現とかちょっとよくわからないですね。
ここはやっぱりDOM的に制御したいですね!
ChromeのWb debuggerをつかってこんなスクリプトを流し込んでみます。

val='';
(function(){
		$.each($('.std input'),
			function(i) {
				val+=$('.std input')[i].value+",";
			}
		)
	}());
val=val.slice(0,val.length-1);

すると、、こんなふうなカンマ区切りのvalueが取得できます。

なので、これに必要な文字列を足してやると、こんなかんじですね。

val='';(function(){$.each($('.std input'),function(i) {val+='http://img.mcdonalds.co.jp/sales/new/smileplus/img/coupon/coupon'+$('.std input')[i].value+'.gif,';})}());val=val.slice(0,val.length-1);

ふぅ。ここまでくれば余裕ですね。

2.てきとうにプロジェクト作って、てきとうにListBoxおいて、x:Nameをlbに、てきとうにWebViewとかおいて、Webviewのx:Nameをwvに、sourceをhttp://www.mcdonalds.co.jp/sales/new/smileplus/index.phpにして、こんなかんじ。

で、ListBoxのDataTemplateのGridの中にImage突っ込んでSourceに
{Binding}
とだけかきます。サイズはHeight=200とかにすればいいかな。

次に、WebViewのLoadCompletedイベントにwv,Invokeにさっきのjs書いて、
カンマ区切りを配列にして、ItemsSourceに突っ込むコードをかいておしまい。

private void WebView_LoadCompleted_1(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
        	var ImageUrl = wv.InvokeScript("eval", new String[] { "val='';(function(){$.each($('.std input'),function(i) {val+='http://img.mcdonalds.co.jp/sales/new/smileplus/img/coupon/coupon'+$('.std input')[i].value+'.gif,';})}());val=val.slice(0,val.length-1);" });
            var ImageUrlArray = ImageUrl.Split(',');
            lb.ItemsSource = lb.ItemsSource = ImageUrlArray;
}

できあがりはこんなかんじ。

で、xaml全文

<Page
    x:Class="App8.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App8"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
	<Page.Resources>
		<DataTemplate x:Key="DataTemplate1">
			<Grid>
				<Image HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Source="{Binding}"/>
			</Grid>
		</DataTemplate>
	</Page.Resources>

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    	<StackPanel Orientation="Horizontal">
    		<WebView x:Name="wv" HorizontalAlignment="Left" Height="382" VerticalAlignment="Top" Width="309" Source="http://www.mcdonalds.co.jp/sales/new/smileplus/index.php" LoadCompleted="WebView_LoadCompleted_1"/>
    		<ListBox x:Name="lb" HorizontalAlignment="Left" Height="382" VerticalAlignment="Top" Width="271" ItemTemplate="{StaticResource DataTemplate1}"/>
    	</StackPanel>
    </Grid>
</Page>

cs全文

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace App8
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private void WebView_LoadCompleted_1(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
        {
        	var ImageUrl = wv.InvokeScript("eval", new String[] { "val='';(function(){$.each($('.std input'),function(i) {val+='http://img.mcdonalds.co.jp/sales/new/smileplus/img/coupon/coupon'+$('.std input')[i].value+'.gif,';})}());val=val.slice(0,val.length-1);" });
            var ImageUrlArray = ImageUrl.Split(',');
            lb.ItemsSource = lb.ItemsSource = ImageUrlArray;
        }
    }
}


あとはよしなにデザインするだけっ!


この方法、応用は聞くし、WebView側に書かれたメソッドも利用できるしとっても楽ちん。
ねっ!簡単でしょう!!