creating turnjs instance before add any pages - pdf.js

I want to add dynamic pages from pdf from page one without cover page. But, I could not create turnjs instance without page inside(cover page that has been hardcoded in html). It output error:
Uncaught (in promise) b {name: "TurnJsError", message: "The page 1 does not exist"}
But, we could not use addpages method of turnjs without declare turnjs instance. How to achieve this?
Currently, I hardcoded cover page in html $('#book').
<div id="book">
<div class="cover">
<h1>Cover</h1>
</div>
</div>
Then, I create turnjs instance as follow:
$('#book').turn({
page: 1,
autoCenter: true,
});
Then, I remove cover page by:
$("#book").turn("removePage", 1);
After that, I start adding pages from pdf. So, it meets my requirement.
Complete code
<?php
ob_start();
require_once('plugin/tcpdf/tcpdf.php');
$pdf = new TCPDF();
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->AddPage();
$html_p1 = 'Text messaging, or texting, is the act of composing and sending electronic messages, typically consisting of alphabetic and numeric characters, between two or more users of mobile devices, desktops/laptops, or other type of compatible computer. Text messages may be sent over a cellular network, or may also be sent via an Internet connection';
//echo $html;
$pdf->writeHTML($html_p1, true, 0, true, 0);
$pdf->AddPage();
$html_p2 = 'A telephone call is a connection over a telephone network between the called party and the calling party.';
$pdf->writeHTML($html_p2, true, 0, true, 0);
$pdf->AddPage();
$html_p3 = 'On the Internet, # (pronounced "at" or "at sign" or "address sign") is the symbol in an e-mail address that separates the name of the user from the users Internet address, as in this hypothetical e-mail address example: msmuffet#tuffet.org. In business, # is a symbol meaning "at" or "each."';
$pdf->writeHTML($html_p3, true, 0, true, 0);
$base64PdfString = $pdf->Output('', 'E');
$base64PdfArray = explode("\r\n", $base64PdfString);
$base64 = '';
for($i = 5; $i < count($base64PdfArray); $i++){
$base64 .= $base64PdfArray[$i];
}
?>
<!doctype html>
<html>
<head>
<style type="text/css">
body
{
background: #ccc;
}
#book
{
width: 800px;
height: 500px;
}
#book .turn-page
{
background-color: white;
}
#book .cover
{
background: #333;
}
#book .cover h1
{
color: white;
text-align: center;
font-size: 50px;
line-height: 500px;
margin: 0px;
}
#book .loader
{
background-image: url(loader.gif);
width: 24px;
height: 24px;
display: block;
position: absolute;
top: 238px;
left: 188px;
}
#book .data
{
text-align: center;
font-size: 40px;
color: #999;
line-height: 500px;
}
#controls
{
width: 800px;
text-align: center;
margin: 20px 0px;
font: 30px arial;
}
#controls input, #controls label
{
font: 30px arial;
}
#book .odd
{
background-image: -webkit-linear-gradient(left, #FFF 95%, #ddd 100%);
background-image: -moz-linear-gradient(left, #FFF 95%, #ddd 100%);
background-image: -o-linear-gradient(left, #FFF 95%, #ddd 100%);
background-image: -ms-linear-gradient(left, #FFF 95%, #ddd 100%);
}
#book .even
{
background-image: -webkit-linear-gradient(right, #FFF 95%, #ddd 100%);
background-image: -moz-linear-gradient(right, #FFF 95%, #ddd 100%);
background-image: -o-linear-gradient(right, #FFF 95%, #ddd 100%);
background-image: -ms-linear-gradient(right, #FFF 95%, #ddd 100%);
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="plugin/turnjs4/lib/turn.min.js"></script>
<script type="text/javascript" src="plugin/pdfjs_ex/pdf.js"></script>
<script>
const b64toBlob = (b64Data, contentType='', sliceSize=512) =>
{
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize)
{
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++)
{
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
function addPage(page, book, pdf_doc)
{
if (!book.turn('hasPage', page))
{
var element = $('<div />', {'class': 'page '+((page%2==0) ? 'odd' : 'even'), 'id': 'page-'+page}).html('<i class="loader"></i>');
book.turn('addPage', element, page);
pdf_doc.getPage((page)).then(function(p)
{
var scale = 1;
var viewport = p.getViewport(scale);
var pag1 =document.createElement('canvas');
pag1.id ='Pg_1';
var context1 =pag1.getContext('2d');
pag1.height =viewport.height;
pag1.width =viewport.width;
var renderContext =
{
canvasContext: context1,
viewport: viewport
};
p.render(renderContext).then(function()
{
pag1.toBlob(function(blob)
{
var burl =URL.createObjectURL(blob);
setTimeout(function()
{
element.html('<div style="background-image:url('+burl+'); width: 400px; height: 500px; background-size: cover;"></div><div style="top: 0px; left: 0px; overflow: hidden; z-index: 1; width: 461px; height: 600px;"></div>');
}, 1000);
})
})
})
}
}
</script>
</head>
<body>
<div id="book">
<div class="cover">
<h1>
Cover
</h1>
</div>
</div>
<script type="text/javascript">
$(window).ready(function()
{
const contentType ='application/pdf';
const b64Data ='<?php echo $base64;?>';
const blob =b64toBlob(b64Data, contentType);
const blobUrl =URL.createObjectURL(blob);
PDFJS.getDocument({ url: blobUrl }).then(function(pdf_doc)
{
__PDF_DOC = pdf_doc;
__TOTAL_PAGES = __PDF_DOC.numPages;
$('#book').turn({
page: 1,
autoCenter: true,
});
var list = [];
for (var i = 1; i <= __TOTAL_PAGES; i++)
{
list.push(i);
}
$("#book").turn("removePage", 1);
for (page = 0; page<list.length; page++)
addPage(list[page], $("#book"),pdf_doc);
})
});
$(window).bind('keydown', function(e)
{
if (e.target && e.target.tagName.toLowerCase()!='input')
if (e.keyCode==37)
$('#book').turn('previous');
else if (e.keyCode==39)
$('#book').turn('next');
});
</script>
</body>
</html>
But, I still want to know how to create turnjs instance with no pages and display as flipbook after adding all pages.

Most probably you are missing 1 line, which is to append the element you created inside addpage() funciton,
you should use
book.append(customDiv);
//OR you can write same thing as:
$('#book').append(element);
// So your Code mus be:
<?php
ob_start();
require_once('plugin/tcpdf/tcpdf.php');
$pdf = new TCPDF();
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->AddPage();
$html_p1 = 'Text messaging, or texting, is the act of composing and sending electronic messages, typically consisting of alphabetic and numeric characters, between two or more users of mobile devices, desktops/laptops, or other type of compatible computer. Text messages may be sent over a cellular network, or may also be sent via an Internet connection';
//echo $html;
$pdf->writeHTML($html_p1, true, 0, true, 0);
$pdf->AddPage();
$html_p2 = 'A telephone call is a connection over a telephone network between the called party and the calling party.';
$pdf->writeHTML($html_p2, true, 0, true, 0);
$pdf->AddPage();
$html_p3 = 'On the Internet, # (pronounced "at" or "at sign" or "address sign") is the symbol in an e-mail address that separates the name of the user from the users Internet address, as in this hypothetical e-mail address example: msmuffet#tuffet.org. In business, # is a symbol meaning "at" or "each."';
$pdf->writeHTML($html_p3, true, 0, true, 0);
$base64PdfString = $pdf->Output('', 'E');
$base64PdfArray = explode("\r\n", $base64PdfString);
$base64 = '';
for($i = 5; $i < count($base64PdfArray); $i++){
$base64 .= $base64PdfArray[$i];
}
?>
<!doctype html>
<html>
<head>
<style type="text/css">
body
{
background: #ccc;
}
#book
{
width: 800px;
height: 500px;
}
#book .turn-page
{
background-color: white;
}
#book .cover
{
background: #333;
}
#book .cover h1
{
color: white;
text-align: center;
font-size: 50px;
line-height: 500px;
margin: 0px;
}
#book .loader
{
background-image: url(loader.gif);
width: 24px;
height: 24px;
display: block;
position: absolute;
top: 238px;
left: 188px;
}
#book .data
{
text-align: center;
font-size: 40px;
color: #999;
line-height: 500px;
}
#controls
{
width: 800px;
text-align: center;
margin: 20px 0px;
font: 30px arial;
}
#controls input, #controls label
{
font: 30px arial;
}
#book .odd
{
background-image: -webkit-linear-gradient(left, #FFF 95%, #ddd 100%);
background-image: -moz-linear-gradient(left, #FFF 95%, #ddd 100%);
background-image: -o-linear-gradient(left, #FFF 95%, #ddd 100%);
background-image: -ms-linear-gradient(left, #FFF 95%, #ddd 100%);
}
#book .even
{
background-image: -webkit-linear-gradient(right, #FFF 95%, #ddd 100%);
background-image: -moz-linear-gradient(right, #FFF 95%, #ddd 100%);
background-image: -o-linear-gradient(right, #FFF 95%, #ddd 100%);
background-image: -ms-linear-gradient(right, #FFF 95%, #ddd 100%);
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="plugin/turnjs4/lib/turn.min.js"></script>
<script type="text/javascript" src="plugin/pdfjs_ex/pdf.js"></script>
<script>
const b64toBlob = (b64Data, contentType='', sliceSize=512) =>
{
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize)
{
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++)
{
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
function addPage(page, book, pdf_doc)
{
if (!book.turn('hasPage', page))
{
var element = $('<div />', {'class': 'page '+((page%2==0) ? 'odd' : 'even'), 'id': 'page-'+page}).html('<i class="loader"></i>');
book.turn('addPage', element, page);
pdf_doc.getPage((page)).then(function(p)
{
var scale = 1;
var viewport = p.getViewport(scale);
var pag1 =document.createElement('canvas');
pag1.id ='Pg_1';
var context1 =pag1.getContext('2d');
pag1.height =viewport.height;
pag1.width =viewport.width;
var renderContext =
{
canvasContext: context1,
viewport: viewport
};
p.render(renderContext).then(function()
{
pag1.toBlob(function(blob)
{
var burl =URL.createObjectURL(blob);
setTimeout(function()
{
element.html('<div style="background-image:url('+burl+'); width: 400px; height: 500px; background-size: cover;"></div><div style="top: 0px; left: 0px; overflow: hidden; z-index: 1; width: 461px; height: 600px;"></div>');
book.append(element);
}, 1000);
})
})
})
}
}
</script>
</head>
<body>
<div id="book">
<div class="cover">
<h1>
Cover
</h1>
</div>
</div>
<script type="text/javascript">
$(window).ready(function()
{
const contentType ='application/pdf';
const b64Data ='<?php echo $base64;?>';
const blob =b64toBlob(b64Data, contentType);
const blobUrl =URL.createObjectURL(blob);
PDFJS.getDocument({ url: blobUrl }).then(function(pdf_doc)
{
__PDF_DOC = pdf_doc;
__TOTAL_PAGES = __PDF_DOC.numPages;
$('#book').turn({
page: 1,
autoCenter: true,
});
var list = [];
for (var i = 1; i <= __TOTAL_PAGES; i++)
{
list.push(i);
}
$("#book").turn("removePage", 1);
for (page = 0; page<list.length; page++)
addPage(list[page], $("#book"),pdf_doc);
})
});
$(window).bind('keydown', function(e)
{
if (e.target && e.target.tagName.toLowerCase()!='input')
if (e.keyCode==37)
$('#book').turn('previous');
else if (e.keyCode==39)
$('#book').turn('next');
});
</script>
</body>
</html>

Related

The script is not output properly

can someone please help me with this? The problem is explained in the video.
https://www.loom.com/share/dba701f22d1c42d38617d9b835d713e4
Here is what I am trying to do, on the input field we will add a youtube video URL and when clicked on the Generate Embed Code button it should output the embed code inside the text aria, do you know why its not working?
<div class="youtube-iframe-generator">
<link href="https://fonts.googleapis.com/css2?family=Roboto+Condensed&display=swap" rel="stylesheet">
<script>
window.onload = setup;
function setup() {
document.getElementById("button").addEventListener("click", go);
document.getElementById("copy-button").addEventListener("click", copy);
}
function setStatus(status, error = false) {
var helpText = document.getElementById("help-text");
helpText.innerText = status;
if (error) {
helpText.style.color = "darkred";
} else {
helpText.style.color = "#227300";
}
}
function go() {
var videoUrl = document.getElementById("input").value;
var videoIdExtractor = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i;
var result = videoIdExtractor.exec(videoUrl);
var EmbedCode = document.getElementById("EmbedCode");
var copyButton = document.getElementById("copy-button");
if (!result) {
EmbedCode.innerHTML = "";
copyButton.disabled = true;
setStatus("Error: Invalid YouTube URL", true);
return;
}
var videoId = result[1];
var finalLink = "https://www.youtube.com/embed/" + videoId;
var imgLink = "https://img.youtube.com/vi/"+videoId+"/maxresdefault.jpg";
var iframe = '<iframe class="youtube-iframe" srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{position: absolute;content: '\f04b';top: 50%;left: 50%;background-color: #6c6cfe;width: 68px;height: 44px;margin-left: -34px;margin-top: -24px;font-size: 30px;color: #fff;text-align: center;line-height: 43px;z-index: 5;border-radius: 6px;}a{display:block;height:100%;}</style><img src="'+imgLink+'" alt="Video The Dark Knight Rises: What Went Wrong? – Wisecrack Edition"><span>▶</span>" frameborder="0" style="aspect-ratio: 16 / 9; width: 100%;" allow="accelerometer; autoplay; encrypted-media; gyroscope;" allowfullscreen></iframe>';
EmbedCode.disabled = false;
copyButton.disabled = false;
EmbedCode.value = iframe;
setStatus("Success! Click the 'Copy' button to copy the embed code.");
}
function copy() {
var EmbedCode = document.getElementById("EmbedCode");
EmbedCode.select();
document.execCommand("copy");
setStatus("Embed code copied to clipboard!");
}
}
</script>
<div class="title">Enter your Youtube URL: <span class="sub">(Scroll down for instructions)</span>
<style>
.youtube-iframe-generator {
font-family: 'Roboto Condensed', sans-serif;
width:96.9%;
}
.title {
font-size: 1.6em;
margin: 15px 0 10px;
}
.sub {
font-size: 0.5em;
color: #444;
vertical-align: middle;
}
#copy-button,
#button {
display: block;
font-family: 'Roboto Condensed', sans-serif;
font-size: 1.2em;
padding: 10px 18px;
margin: 15px auto;
border: none;
border-radius: 3px;
background: #598cff;
color: #ffffff;
cursor: pointer;
box-shadow: 0 2px 3px 0px #b5b5b5;
transition: background 200ms;
}
#copy-button:hover,
#button:hover {
background: #6b99ff;
}
#copy-button:active,
#button:active {
background: #598cff;
box-shadow: 0 2px 3px -1px #b5b5b5;
}
#input{
font-size: 1.1em;
display: block;
width: 100%;
padding: 10px;
border: 1px solid #b5b5b5;
border-radius: 3px;
}
#EmbedCode {
font-size: 1.1em;
display: block;
width: 100%;
padding: 10px;
border: 1px solid #b5b5b5;
border-radius: 3px;
resize: vertical;
overflow: auto;
}
#help-text {
font-weight: 600;
margin: 10px;
}
</style>
</div>
<input id="input" type="text" placeholder="https://www.youtube.com/watch?v=h4iRMtQBGAk">
<button id="button">Generate Embed Code</button>
<div class="title">Embed Code:</div>
<textarea id="EmbedCode" type="text" readonly="" disabled=""></textarea>
<button id="copy-button" disabled> <i class="fa-regular fa-clipboard"></i> Copy Embed Code</button>
<div id="help-text"></div>
</div>

Webview render issue on iOS [Testflight]

I'm trying to render a webview in my flutter project.
It's working perfectly for Android in debug and release modes and on iOS in debug mode as well.
However if I upload a build to Testflight, it does not work for some reason.
I've been working with the same code from the past few months and not had an issue with Flutter v1.
I'm attaching a code snippet below. Any help is appreciated.
Snippet:
return Container(
width: size.width,
height: size.height,
child: WebView(
key: UniqueKey(),
initialUrl: renderHTML(width, content!),
javascriptMode: JavascriptMode.unrestricted,
javascriptChannels: <JavascriptChannel>[
JavascriptChannel(
name: 'GetImgSrc',
onMessageReceived: (JavascriptMessage msg) {
print('Stef Method Channel ${msg.message}');
Navigator.of(context)
.pushNamed(PhotoViewer.route, arguments: msg.message);
}),
].toSet(),
navigationDelegate: (request) => NewsArticleController()
.navigationDelegate(request, content!, width),
),
);
renderHtml(width, content) {
return Uri.dataFromString(body, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString();
}
Html Snippet:
String body = '''
<html>
<head>
<meta name='viewport' content='initial-scale = 1.0, width=device-width'/>
<style>
html {
width: ${width}px;
}
body {
margin-left: 8px;
margin-right: 8px;
margin-top: 0px;
margin-bottom: 0px;
background-color: #F6F6F6;
}
em {
font-style: italic;
}
.title {
padding: 0 20px;
font-family: Georgia,Times,Times New Roman,serif;
font-size: 20px;
font-weight: 600;
letter-spacing: 1px;
line-height: 32px;
color:#3D3D3D;
}
.meta-desc {
margin: 8px 0;
font-size: 16px;
text-align: left;
color: #000000;
font-family: Georgia,Times,Times New Roman,serif;
font-weight: 400;
line-height: 24px;
letter-spacing: 1px;
}
.meta-data {
padding: 12px 0 8px 20px;
color:#818181;
font-size: 12px;
line-height: 20px;
font-family: Georgia,Times,Times New Roman,serif;
}
.hero-img img {
margin-left: -8px;
width: ${double.parse(width)}px;
height: auto;
}
.body-content {
padding: 0 20px;
}
.body-content div, .body-content p, .body-content span {
padding: 0 !important;
margin-bottom: 15px !important;
font-size: 20px;
text-align: left;
color: #000000;
font-family: Georgia,Times,Times New Roman,serif;
font-weight: 400;
line-height: 31px;
}
.body-content img {
width: 100%;
height: auto;
margin: auto;
}
a {
color: #F50057;
text-decoration: none;
font-weight: bold;
}
.yt-iframe {
width: ${double.parse(width) - 16}px;
min-height: 200px;
}
iframe.instagram-media {
margin: 0 auto 10px !important;
/* width: ${double.parse(width) - 16}px !important; */
}
iframe {
margin: 0 8px 10px -8px !important;
width: 100% !important;
}
</style>
</head>
<body>
<div class="hero-img cls-image">
<img src="${content.images?.url}">
</div>
<div style="text-align: end; padding: 16px 20px 8px 0; font-size:12px; color:#818181;">${content.postDateStr}</div>
<div class="title">
${content.title}
</div>
<!--<div class="meta-desc">
${content.metaTagDescription}
</div>-->
<div class="meta-data">
By <span>${content.user}</span>
</div>
<div class="body-content">
$body
</div>
</body>
<script>
var elements = document.getElementsByClassName("instagram-media");
setTimeout(function(){
for (var i = 0; i < elements.length; i++) {
elements[i].style.width=('0px');
console.log('initial width: ' + elements[i].style.width);
elements[i].style.width=('${double.parse(width) - 16}px');
console.log('final width: ' + elements[i].style.width);
}
console.log(elements);
}, 1000);
var images = document.getElementsByClassName("cls-image");
var myFunction = function(event) {
GetImgSrc.postMessage(event.target.src);
};
for (var i = 0; i < images.length; i++) {
images[i].addEventListener('click', myFunction, false);
}
</script>
</html>
''';
Flutter version: Channel stable, 2.2.3, on macOS 11.4 20F71 darwin-x64, locale en-US
webview_flutter version: 2.0.9
You may need to do more setup for the WebView to work with IOS build - if you're using this package I would suggest taking a look at this and adding in suggested info to your info.plist
https://inappwebview.dev/docs/get-started/setup-ios/

ruby on rails create loop inside onclick

How can I make a loop inside currentSlide(1) so I want everytime .each work to add currentSlide(1) then currentSlide(2) then currentSlide(3) and so on.
<div class="approach" id="app">
<style>
#media (max-width: 600px){
.btn {
padding: 2px 2px 2px 2px !important; */
}}
#myBtnContainer{
display: flex;
}
/* Create three equal columns that floats next to each other */
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 282px;
}
.column:hover{
border: 1px solid #777;
}
/* Clear floats after rows */
.row:after {
content: "";
display: table;
clear: both;
}
/* Content */
.content {
width: 100%;
height: 400px;
overflow: hidden;
/*display: flex;*/
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
}
.content img{
object-fit: cover;
height: auto;
width: 100%;
position: absolute;
}
/* The "show" class is added to the filtered elements */
.show {
display: block;
}
/* Style the buttons */
.btn {
border: none;
outline: none;
padding: 10px 10px;
background-color: #333333;
cursor: pointer;
color: white;
}
.btn:hover {
background-color: #ddd;
}
.btn.active {
background-color: #666;
color: white;
}
.modal {
display: none;
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: black;
}
/* Modal Content */
.modal-content {
position: relative;
background-color: #fefefe;
margin: auto;
padding: 0;
width: 90%;
max-width: 500px;
}
/* The Close Button */
.close {
color: white !important;
position: absolute;
top: 170px;
right: 25px;
font-size: 35px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #999;
text-decoration: none;
cursor: pointer;
}
.mySlides {
display: none;
}
.cursor {
cursor: pointer
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -50px;
color: white;
font-weight: bold;
font-size: 20px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
}
/* Position the "next button" to the right */
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
/* On hover, add a black background color with a little bit see-through */
.prev:hover,
.next:hover {
background-color: rgba(0, 0, 0, 0.8);
}
/* Number text (1/3 etc) */
.numbertext {
color: #f2f2f2;
font-size: 12px;
padding: 8px 12px;
position: absolute;
top: 0;
}
img {
margin-bottom: -4px;
}
.caption-container {
text-align: center;
background-color: black;
padding: 2px 16px;
color: white;
}
.demo {
opacity: 0.6;
}
.active,
.demo:hover {
opacity: 1;
}
img.hover-shadow {
transition: 0.3s
}
.hover-shadow:hover {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)
}
.mySlides img{
padding-top: 70px;
background-color: black;
}
div.desc {
padding: 15px;
text-align: center;
}
#media (max-width:600px) {
.close {
color: white !important;
position: absolute;
top: 120px;
right: 25px;
font-size: 45px;
font-weight: bold;
z-index: 1000;
}
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 83px;
}
}
#media (max-width: 320px){
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 70px;
}
}
#media only screen and (min-width: 812px) {
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 90px;
} }
</style>
<body>
<!-- MAIN (Center website) -->
<div class="container">
<h1>GALLERY</h1>
<div id="myBtnContainer">
<button class="btn" onclick="filterSelection('conversion')"> Conversion</button>
<button class="btn" onclick="filterSelection('fixed-hybrid')"> Fixed Hybrid</button>
<button class="btn" onclick="filterSelection('removal-bar-over-denture')"> Removable Bar Over Denture</button>
<button class="btn" onclick="filterSelection('surgical-guides')"> Surgical Guides</button>
<button class="btn active" onclick="filterSelection('all')"> Show all</button>
</div>
<br>
<!-- Portfolio Gallery Grid -->
<div class="row">
<% #galleries.each do |g| %>
<% [g.image1, g.image2, g.image3, g.image4, g.image5].compact.each_with_index do |image, index| %>
<div class="column <%= g.product_name %>">
<div class="content">
<%= image_tag image.url, style: "width:100%", onclick: "openModal();currentSlide(#{index + 1})" ,class: "hover-shadow cursor"%>
</div>
</div>
<% end %>
<% end %>
<!-- END GRID -->
</div>
<!-- END MAIN -->
</div>
<div id="myModal" class="modal">
<span class="close cursor" onclick="closeModal()">×</span>
<div class="modal-content">
<% #galleries.each do |g| %>
<% [g.image1, g.image2, g.image3, g.image4, g.image5].compact.each_with_index do |image, index| %>
<div class="mySlides">
<div class="numbertext">1 / 4</div>
<%= image_tag image.url, style: "width:100%" %>
</div>
<% end %>
<% end %>
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
<div class="caption-container">
<p id="caption">hr</p>
</div>
</div>
<script>
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("column");
if (c == "all") c = "";
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
}
}
function w3AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {element.className += " " + arr2[i];}
}
}
function w3RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
// Add active class to the current button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function(){
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
</script>
</div>
<script>
function openModal() {
document.getElementById('myModal').style.display = "block";
}
function closeModal() {
document.getElementById('myModal').style.display = "none";
}
var slideIndex = 1;
showSlides(slideIndex);
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("demo");
var captionText = document.getElementById("caption");
if (n > slides.length) {slideIndex = 1}
if (n < 1) {slideIndex = slides.length}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " active";
captionText.innerHTML = dots[slideIndex-1].alt;
}
</script>
Looks like you just need an index to interpolate into currentSlide.
Start by removing duplication and instead of checking every related image with <% if g.image1.present? %> put them into an array and iterate over it with:
<% [g.image1, g.image2, g.image3].compact.each_with_index do |image, index|
compact will make sure that only present images are there, so you don't have to use if present any more.
And then use onclick: "openModal();currentSlide(#{index + 1})" (as index starts at 0, and you seem to need it to start from 1)
Update:
<% #galleries.each do |g| %>
<% [g.image1, g.image2, g.image3, g.image4, g.image5].compact.each_with_index do |image, index| %>
<div class="column <%= g.product_name %>">
<div class="content">
<%= image_tag image.url,
alt: "conversion",
style: "width:100%",
onclick: "openModal();currentSlide(#{index + 1})",
class: "hover-shadow cursor" %>
</div>
</div>

How to handle IF statement in AMP and .NET

#using App
#using Helpers
#model App.Model.Cache
#{
ViewBag.Title = #Model.Title;
Layout = null;
}
<!doctype html>
<html ⚡>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}#-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-element="amp-social-share" src="https://cdn.ampproject.org/v0/amp-social-share-0.1.js"></script>
<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>
<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
<script async custom-element="amp-ad" src="https://cdn.ampproject.org/v0/amp-ad-0.1.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato"/>
#if (!Model.IsBookmark)
{
<link rel="canonical" href="#(Model.CanonicalUrl())"/>
}
else
{
<link rel="canonical" href="#Model.BookmarkURL"/>
}
<style amp-custom>
body {font-family:Lato, Arial;}
.related {
background-color: #f5f5f5;
display: block;
clear: both;
height: 64px;
margin-bottom: 14px;
}
.related > span {
font-size: 16px;
font-weight: 400;
vertical-align: middle;
margin: 8px;
line-height: 1.2em;
height: 64px;
}
.related:hover {
background-color: #ccc;
}
.related-recipes a {
text-decoration: none;
color: #444;
}
.related-image {
width: 64px;
height: 64px;
float: left;
}
.related-text {
display: inline;
vertical-align: middle;
color: #111;
position: relative;
top: 1.2em;
left: .9em;
text-overflow: clip;
word-break: break-all;
word-wrap: break-word;
}
amp-carousel amp-img > img {
object-fit: contain;
}
amp-carousel figcaption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 8px;
background: rgba(0, 0, 0, 0.6); /* translucent black */
color: #ddd;
font-size: smaller;
max-height: 30%;
}
amp-carousel .review {
width: 25em;
vertical-align: top;
overflow: auto;
margin: 0;
padding: 16px;
height: 80%; /* TODO easy way to ensure the bottom shadow is visible */
white-space: normal; /* the enclosing div generated by amp-carousel sets it to nowrap */
}
amp-carousel .review:nth-child(even) {
background: #FFFFFF
}
amp-carousel .review:nth-child(odd) {
background: #94C2F9
}
amp-carousel .review h1 {
font-size: larger;
padding: 0;
}
amp-carousel .review p {
padding: 0;
}
amp-carousel .review address:before {
content: '-- ';
}
ul, ol {
padding: 0 16px;
}
/* Unicode-based stars and half-star credit: amoniker, https://coderwall.com/p/iml9ka/star-ratings-in-css-utf8 */
.star-icon {
color: #ddd;
font-size: 34px;
position: relative;
}
.star-icon.full:before {
color: #FDE16D;
content: '\2605'; /* Full star in UTF8 */
position: absolute;
left: 0;
text-shadow: 0 0 2px rgba(0, 0, 0, 0.7);
}
.star-icon.half:before {
color: #FDE16D;
content: '\2605'; /* Full star in UTF8 */
position: absolute;
left: 0;
width: 50%;
overflow: hidden;
text-shadow: 0 0 2px rgba(0, 0, 0, 0.7);
}
.logo {
background-position: left 16px center;
background-repeat: no-repeat;
background-image: url(https://www.bigoven.com/assets/images/icons/bigoven-recipes.png);
background-color: #fefefe;
height: 38px;
text-align: left;
padding: 16px;
padding-left: 72px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12);
}
.logo > a {
text-decoration: none;
}
.heading {
text-align: center;
padding-bottom: 8px;
}
.heading > #summary {
font-weight: 500;
}
.heading > small {
color: #656565;
}
.lower-wrapper {
margin: 0em 1em 0em 1em;
}
.title-description {
max-width: 310px;
margin: 0 auto;
}
</style>
</head>
<body>
<div>
...
</div>
</body>
</html>
I'm having a problem with writing correct 'IF' statement in .NET and AMP. Statment look like this and it placed in a head section where suppose to be. AMP Validator throws me three errors:
Tag outside the body section
and two of 'link rel=cannonical' is 'body', but it can only be 'head'
Here is a code snippet of my if statement from my cshtml template:
#if (!Model.IsBookmark)
{
<link rel="canonical" href="#(Model.CanonicalUrl())"/>
}
else
{
<link rel="canonical" href="#Model.BookmarkURL"/>
What is the correct way to handle if statement in AMP?

jQuery UI draggable locking divs

I wrote some kind of that: http://jsfiddle.net/py3DE/203/ but when element is dragged into proper container, we can override it by dragging other div into its area. Could you tel me how i can block dragged elements, and if someone will try to override any element, div returns back into area with undragged divs?
if (!ui.draggable.closest('.empty').length) item = item.draggable()'
There is a simple way to do this. Basically, we'll remove the class empty and use the disable method.
Working Example: http://jsfiddle.net/Twisty/5rdxmp4p/
Minor CSS Change
.filled .item .closer {
display: block;
}
Drop Function
drop: function(ev, ui) {
if ($(this).hasClass("empty")) {
$(this).removeClass("empty").addClass("filled");
$(this).droppable("disable");
} else {
return false;
}
var item = ui.draggable;
if (!ui.draggable.closest('.empty').length) item = item.draggable(); // if item was dragged from the source list - clone it
this.innerHTML = ''; // clean the placeholder
item.css({
top: 0,
left: 0
}).appendTo(this); // append item to placeholder
}
Swapping the class allows the X button to appear. We then run the disable method to ensure that this specific item will no longer accept a dragged item. If the user drags an item to this spot, it is then reverted.
Update
Using Sortable: http://jsfiddle.net/Twisty/5rdxmp4p/2/
HTML
<div id="dragItems" class="source">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
</div>
<div id="sortItems" class="target">
</div>
CSS
body {
background: #fff;
}
.source,
.target {
margin: 20px;
min-height: 190px;
width: 400px;
border: 1px solid green;
}
.target {
border: 1px solid blue;
}
.item {
height: 20px;
margin: 5px;
padding: 5px;
border: 1px solid gray;
background-color: #cd8;
position: relative;
}
.closer {
float: right;
width: 20px;
height: 20px;
border: 0;
background-color: transparent;
}
.closer:hover {
background-color: transparent;
border: 0;
}
.empty {
height: 30px;
margin: 5px;
background: #eee;
border: 1px dashed #999;
}
.highlight {
border: 1px solid red;
background: #fff;
}
.highlight .item {
opacity: 0.3;
}
.ui-draggable-dragging {
z-index: 99;
opacity: 1 !important;
width: 378px;
}
jQuery
$(function() {
$("#sortItems").sortable({
axis: "y",
items: "> div",
placeholder: "empty",
dropOnEmpty: true,
stop: function(e, ui) {
var $it = ui.item;
if ($it.find(".closer").length == 0) {
var closeBtn = $("<span>", {
class: "closer"
});
$it.append(closeBtn);
closeBtn.button({
icon: "ui-icon-close",
label: "Close",
showLabel: false
}).click(function(ev) {
console.log("[INFO]: Closing ", $it);
$it.fadeTo(200, 0.0, function() {
$it.remove();
$("#sortItems").sortable("refresh");
});
});
}
}
});
$("#dragItems .item").draggable({
connectToSortable: "#sortItems",
revert: "invalid"
});
$("#sortItems").disableSelection();
});

Resources