vov-mobile

Check-in [0b51195174]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Move images to VoV web site. Pull banners dynamically. Implement URL click (window open) for banner entries.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | master | trunk
Files: files | file ages | folders
SHA3-256:0b511951748a68038345234ae75640274cc33f99d2c8ff40baa597d8cdbd342c
User & Date: ajv-899-334-8894@vsta.org 2016-08-20 16:50:24
Context
2016-08-20
16:52
Merge branch 'master' of https://github.com/vandys/vov-mobile check-in: 72d9d0f7e9 user: ajv-899-334-8894@vsta.org tags: master, trunk
16:50
Move images to VoV web site. Pull banners dynamically. Implement URL click (window open) for banner entries. check-in: 0b51195174 user: ajv-899-334-8894@vsta.org tags: master, trunk
15:15
Use delay to make stream and Now Playing line up better check-in: 9150567bce user: ajv-899-334-8894@vsta.org tags: master, trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added imgs.css.









>
>
>
>
1
2
3
4
/* Switch to "move" cursor */
.draggable {
    cursor: move;
}

Changes to imgs.js.

1












2
3




4
5
6














7
8
9
10
11
12
13
14
15


16
17
18
19
20
21
22
..
24
25
26
27
28
29
30


31
32
33
34
35
36
37
38
39





40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98



99
100
101
102
103
104
105
106
107
108
109
110
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128

129
130
131



































132
133
134
135
136
137
138
139
// Which banner image is current displayed; 0 == "BannerA.jpg"












var curpic = 0;





// We've seen the mouse button pressed
// We only care about X, for side-sliding
var pressX = null;















// Mouse down on our banner tiles, see if they're really
//  going to drag them.
function bandown(evt) {
    if (pressX == null) {
	touch_handle = "mousemove";
	touch_handler = banmove;
	slider.addEventListener("mousemove", banmove);
	pressX = evt.pageX;


    }
    evt.stopPropagation();
}
// Touch down
function bantdown(evts) {
    if (evts.targetTouches.length != 1) {
	return;
................................................................................
    if (pressX == null) {
	var evt = evts.targetTouches[0];

	touch_handle = "touchmove";
	touch_handler = bantmove;
	slider.addEventListener("touchmove", bantmove);
	pressX = evt.pageX;


    }
    evts.stopPropagation();
}

// Mouse up or off screen
function bandone() {
    if (pressX != null) {
	slider.removeEventListener(touch_handle, touch_handler);
	pressX = touch_handle = touch_handler = null;





    }
}

// Current top left corner of viewbox (Y never changes)
var viewbX = 0;

// When animated, timestamp for start and desired X corner
//  for the viewBox
var running = false;
var animTM = null;
var targX = null;

// Move the viewBox
function banstep() {
    // Target completion in 1 second
    var pct = (Date.now() - animTM) / 1000.0;

    // Done?
    if (pct >= 1.0) {
................................................................................
    targX = curpic*BWIDTH;
    if (!running) {
	requestAnimationFrame(banstep);
	running = true;
    }
}

// Pixels width of each banner to display
const BWIDTH = 640;

// Number of banners, starting at BannerA
const NBAN = 4;

// Once they've moved enough X distance, try and rotate
//  to the new image.
function domove(pageX) {
    if (Math.abs(pressX - pageX) < BWIDTH/3) {



	return;
    }

    var toleft = (pressX > pageX);
    bandone();
    if (toleft) {
	// The pointer moved to the left, dragging, so
	//  we want the next thing on the right to
	//  slide in.
	if (curpic < (NBAN-1)) {
	    curpic += 1;
	    banmotion();
................................................................................
	    banmotion();
	}
    }
}

// Interface from mouse
function banmove(evt) {
    domove(evt.pageX);
}

// Interface from touch
function bantmove(evt) {
    if (evt.targetTouches.length == 1) {
	domove(evt.targetTouches[0].pageX);

    }
}




































// If available, set screen orientation
if (screen.orientation != null) {
    screen.orientation.lock("portrait").catch(function () {
	// Probably a desktop browser without
	//  orientation support.
	console.log("Orientation not lockable");
    });
}
|
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>







 







>
>





|


|
>
>
>
>
>



<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<


|
|
>
>
>




|







 







|





|
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81









82
83
84
85
86
87
88
...
112
113
114
115
116
117
118






119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
//
// imgs.js
//	Handle rotating banner images in web page
//

// Pixel width of each banner to display
const BWIDTH = 640;

// Number of banners
var NBAN = 0;

// How far they've moved while holding down
// (X *and* Y, so we can verify a true click.)
var curdist = null;

// If they hold down and move less than this distance before
//  releasing, call it a click.
const CLICKDIST = BWIDTH/20;

// We've seen the mouse button pressed
// We only care about X, for side-sliding
var pressX = null, pressY = null;

// Which banner image is current displayed; 0 == first
var curpic = 0;
// Map from curpic value to dispatch URL
var pics = {};

// Current top left corner of viewbox (Y never changes)
var viewbX = 0;

// When animated, timestamp for start and desired X corner
//  for the viewBox
var running = false;
var animTM = null;
var targX = null;

// Mouse down on our banner tiles, see if they're really
//  going to drag them.
function bandown(evt) {
    if (pressX == null) {
	touch_handle = "mousemove";
	touch_handler = banmove;
	slider.addEventListener("mousemove", banmove);
	pressX = evt.pageX;
	pressY = evt.pageY;
	curdist = 0;
    }
    evt.stopPropagation();
}
// Touch down
function bantdown(evts) {
    if (evts.targetTouches.length != 1) {
	return;
................................................................................
    if (pressX == null) {
	var evt = evts.targetTouches[0];

	touch_handle = "touchmove";
	touch_handler = bantmove;
	slider.addEventListener("touchmove", bantmove);
	pressX = evt.pageX;
	pressY = evt.pageY;
	curdist = 0;
    }
    evts.stopPropagation();
}

// Mouse up or off screen
function bandone(moved) {
    if (pressX != null) {
	slider.removeEventListener(touch_handle, touch_handler);
	pressX = pressY = touch_handle = touch_handler = null;
	if (!moved) {
	    if (curdist < CLICKDIST) {
		window.open(pics[curpic]);
	    }
	}
    }
}










// Move the viewBox
function banstep() {
    // Target completion in 1 second
    var pct = (Date.now() - animTM) / 1000.0;

    // Done?
    if (pct >= 1.0) {
................................................................................
    targX = curpic*BWIDTH;
    if (!running) {
	requestAnimationFrame(banstep);
	running = true;
    }
}







// Once they've moved enough X distance, try and rotate
//  to the new image.
function domove(pageX, pageY) {
    var distx = Math.abs(pressX - pageX);
    var disty = Math.abs(pressY - pageY);
    curdist = Math.sqrt(distx*distx + disty*disty);
    if (distx < BWIDTH/3) {
	return;
    }

    var toleft = (pressX > pageX);
    bandone(true);
    if (toleft) {
	// The pointer moved to the left, dragging, so
	//  we want the next thing on the right to
	//  slide in.
	if (curpic < (NBAN-1)) {
	    curpic += 1;
	    banmotion();
................................................................................
	    banmotion();
	}
    }
}

// Interface from mouse
function banmove(evt) {
    domove(evt.pageX, evt.pageY);
}

// Interface from touch
function bantmove(evt) {
    if (evt.targetTouches.length == 1) {
	domove(evt.targetTouches[0].pageX,
	    evt.targetTouches[0].pageY);
    }
}

// Create a new SVG <image ...> element
function newimage() {
    return document.createElementNS("http://www.w3.org/2000/svg",
	"image");
}

// Punch in our banners as described in JSON
function got_banners(req) {
    var panels = JSON.parse(req.responseText);
    for (var idx = 0; idx < panels.length; ++idx) {
	var p = panels[idx];

	// SVG image element
	var svgimg = newimage();
	svgimg.x.baseVal.value = idx*BWIDTH;
	svgimg.y.baseVal.value = 0;
	svgimg.height.baseVal.value = 100;
	svgimg.width.baseVal.value = BWIDTH;
	svgimg.className.baseVal = "draggable";
	svgimg.href.baseVal = p["image"];

	// Under the "slider" SVG parent
	slider.appendChild(svgimg);

	// Register a URL to open when they click
	pics[idx] = p["url"];

	// Count'em
	NBAN += 1;
    }
}

// Get our banner list
ajax_http_get("/APP/rotating_banners.json", got_banners);

// If available, set screen orientation
if (screen.orientation != null) {
    screen.orientation.lock("portrait").catch(function () {
	// Probably a desktop browser without
	//  orientation support.
	console.log("Orientation not lockable");
    });
}

Changes to index.html.

2
3
4
5
6
7
8

9
10
11
12
13
14
15
..
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
..
97
98
99
100
101
102
103
104
105

106
107
108
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Voice of Vashon - Mobile WWW</title>
</head>

<link rel="stylesheet" href="style.css">


<body>

<audio id="radio1"></audio>
<script src="radio.js"></script>

<div class="shadowed" style="text-align: center; background: #1a75ff;">
................................................................................
  <td width="30%" style="text-align: left; font-weight: bold">
   <input type="radio" name="channel" id="kvshbtn" value="kvsh" checked>KVSH FM<br>
   <input type="radio" name="channel" value="1650am">1650 AM
  </td>
  <td width="20%">
   <img id="playmode" width="48px" height="48px" style="display: block; margin: 0 auto"
     onclick="return playBtn();"
     src="http://amrivalencia.com/icon/play.svg">
  </td>
  <td width="40%"></td>
  <td width="20%"></td>
<td width="20%"></td>
</tr>
</table>

<table style="width: 100%;">
<tr>
 <td style="width: 10%;"></td>
 <td style="width: 80%;">
  <svg id="slider" preserveAspectRatio="xMidYMin" viewBox="0 0 640 100"
	onmousedown="bandown(evt);" ontouchstart="bantdown(evt);"
	onmouseup="bandone();" onblur="bandone();"
	ontouchend="bandone();"
>
    <image x="0" y="0" height="80" width="640"
	class="draggable"
	xlink:href="http://voiceofvashon.org/APP/BannerA.jpg" />
    <image x="640" y="0" height="100" width="640"
	class="draggable"
	xlink:href="http://voiceofvashon.org/APP/BannerB.jpg" />
    <image x="1280" y="0" height="100" width="640"
	class="draggable"
	xlink:href="http://voiceofvashon.org/APP/BannerC.jpg" />
    <image x="1920" y="0" height="100" width="640"
	class="draggable"
	xlink:href="http://voiceofvashon.org/APP/BannerD.jpg" />
  </svg>
 </td>
 <td style="width: 10%;"></td>
</tr>
</table>
</div>

................................................................................
>
</iframe>

</td>
</tr>
</table>

<script src="imgs.js"></script>
<script src="nowplaying.js"></script>


</body>
</html>







>







 







|













|
|

<
<
<
<
<
<
<
<
<
<
<
<







 







<

>



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
..
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65












66
67
68
69
70
71
72
..
86
87
88
89
90
91
92

93
94
95
96
97
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Voice of Vashon - Mobile WWW</title>
</head>

<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="imgs.css">

<body>

<audio id="radio1"></audio>
<script src="radio.js"></script>

<div class="shadowed" style="text-align: center; background: #1a75ff;">
................................................................................
  <td width="30%" style="text-align: left; font-weight: bold">
   <input type="radio" name="channel" id="kvshbtn" value="kvsh" checked>KVSH FM<br>
   <input type="radio" name="channel" value="1650am">1650 AM
  </td>
  <td width="20%">
   <img id="playmode" width="48px" height="48px" style="display: block; margin: 0 auto"
     onclick="return playBtn();"
     src="http://voiceofvashon.org/mobile/icon/play.svg">
  </td>
  <td width="40%"></td>
  <td width="20%"></td>
<td width="20%"></td>
</tr>
</table>

<table style="width: 100%;">
<tr>
 <td style="width: 10%;"></td>
 <td style="width: 80%;">
  <svg id="slider" preserveAspectRatio="xMidYMin" viewBox="0 0 640 100"
	onmousedown="bandown(evt);" ontouchstart="bantdown(evt);"
	onmouseup="bandone(false);" onblur="bandone(false);"
	ontouchend="bandone(false);"
>












  </svg>
 </td>
 <td style="width: 10%;"></td>
</tr>
</table>
</div>

................................................................................
>
</iframe>

</td>
</tr>
</table>


<script src="nowplaying.js"></script>
<script src="imgs.js"></script>

</body>
</html>

Changes to radio.js.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
}

function playBtn() {
    // If playing, turn it off & update play button
    if (playing) {
	radio1.pause();
	playing = rolling = false;
	playmode.src = "http://amrivalencia.com/icon/play.svg";
	return false;
    }

    // Update icon; clicking now stops us
    playmode.src = "http://amrivalencia.com/icon/pause.svg";

    // Start playing with preroll
    playing = rolling = true;
    if (kvshbtn.checked) {
	radio1.src = "http://voiceofvashon.org/APP/PreRoll_KVSH.mp3";
    } else {
	radio1.src = "http://voiceofvashon.org/APP/PreRoll_1650.mp3";
    }
    radio1.addEventListener("ended", doneRoll);
    radio1.play()

    return false;
}







|




|













19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
}

function playBtn() {
    // If playing, turn it off & update play button
    if (playing) {
	radio1.pause();
	playing = rolling = false;
	playmode.src = "http://voiceofvashon.org/mobile/icon/play.svg";
	return false;
    }

    // Update icon; clicking now stops us
    playmode.src = "http://voiceofvashon.org/mobile/icon/pause.svg";

    // Start playing with preroll
    playing = rolling = true;
    if (kvshbtn.checked) {
	radio1.src = "http://voiceofvashon.org/APP/PreRoll_KVSH.mp3";
    } else {
	radio1.src = "http://voiceofvashon.org/APP/PreRoll_1650.mp3";
    }
    radio1.addEventListener("ended", doneRoll);
    radio1.play()

    return false;
}