Dojo grid not scrolling to last item - dojo

I'm teaching myself javascript by building a very basic web based chat application.
Chat messages are posted to a web server. An HTML chat Client polls the web server periodically to download any new messages.
The chat messages are displayed using a dojo grid.
My problem is that I can't scroll the grid to the last message. I have tried using scrollToRow but it doesn't work.
The javascript code is here =>
<html>
<head>
<style type="text/css">
#import "./dojoroot/dojo/resources/dojo.css";
#import "./dojoroot/dijit/themes/tundra/tundra.css";
#import "./dojoroot/dojox/grid/resources/Grid.css";
#import "./dojoroot/dojox/grid/resources/tundraGrid.css";
.input {
width: 100%;
padding: 0;
text-align: justify;
}
.dojoxGridHeader {
display: none;
}
</style>
<script language="JavaScript" src="./dojoroot/dojo/dojo.js" djConfig="isDebug: false, parseOnLoad: true">
</script>
<script type="text/Javascript">
dojo.require("dojo.parser");
dojo.require("dojo.dom-style");
dojo.require("dojox.grid.DataGrid");
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.layout.ContentPane");
var chatData={items:[]};
var chatStore=new dojo.data.ItemFileWriteStore({data:chatData});
var chatLayout=[[{'name':'Sender','field':'sender','width':'10%'},
{'name':'Message','field':'message','width':'90%'}]];
var chatRow=0;
</script>
</head>
<body>
<div align="center">
<div dojoType="dijit.layout.ContentPane" sizeMin="10" sizeShare="10">
<div id="gridDiv" style="text-align:left; border: 1px solid #aaa; width:98%; height:80%; overflow:auto;">
</div>
</div>
<script type="text/javascript">
var grid=new dojox.grid.DataGrid({id:'grid',
store:chatStore,
structure:chatLayout,
rowSelector:'0px'});
grid.placeAt("gridDiv");
grid.startup();
setInterval(listenToServer,250);
function listenToServer() {
dojo.xhrGet({
url: "http://localhost:8080/ChatProject/ListenToServer",
handleAs: "json",
load: function(data) {
if (data!=null) {
if (data.message!="") {
var myNewItem = {sender: data.sender, message: data.message};
chatRow++;
// Insert the new item into the store:
// (we use store3 from the example above in this example)
chatStore.newItem(myNewItem);
chatStore.save();
var lastRow=grid.store._arrayOfAllItems.length-1;
grid.scrollToRow(lastRow);
}
}
}
});
}
</script>
</body>
</html>
The grid does not scroll down to the last message.
Any help would be much appreciated.
Thanks.
James.

After much experimentation I discovered the following issues:
two separate scroll bars were being created - I assume (although I am not sure) that one scroll bar was associated with the content pane and one with the grid. For the grid I set overflow:hidden to overcome this.
the height:80% parameter was causing the grid to be bigger than the surrounding content pane. I changed this to height:250px.
With these two changes the scrolling started to work (almost).
At this point I encountered this bug in dataGrid => https://bugs.dojotoolkit.org/ticket/10487
At that point I moved on and stopped using dataGrid!

Related

Vue Prism Editor - set tabSize

im currently digging through the github page, but Im unable to figure out how to set the tabSize property on my prism editor, if anyone has any experience and is willing to share it I would greatly appreciate it!
I will answer here as I placed in code snippet for you to play with.
There is a problem on the umd script where it cannot recognise tabSize as a valid props.
Therefore, you can use tab-size to overcome this.
P.S. move tab size to be part of vue data to avoid complaining the type.
Here is the code snippet for you to test it.
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
<link rel="stylesheet" href="https://unpkg.com/vue-prism-editor/dist/prismeditor.min.css" />
<link rel="stylesheet" href="https://unpkg.com/prismjs/themes/prism-tomorrow.css" />
<style>
.height-200 {
height: 200px
}
.my-editor {
/* we dont use `language-` classes anymore so thats why we need to add background and text color manually */
background: #2d2d2d;
color: #ccc;
/* you must provide font-family font-size line-height. Example:*/
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
font-size: 14px;
line-height: 1.5;
padding: 5px;
}
/* optional class for removing the outline */
.prism-editor__textarea:focus {
outline: none;
}
</style>
</head>
<body>
<div id="app">
<prism-editor class="my-editor height-200" v-model="code" :highlight="highlighter" line-numbers :tab-size="tabSize">
</prism-editor>
</div>
<script src="https://unpkg.com/vue#2.6.*"></script>
<script src="https://unpkg.com/vue-prism-editor"></script>
<script src="https://unpkg.com/prismjs/prism.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
<!-- <script src="./src/index.js"></script> -->
<script>
new Vue({
el: "#app",
data: () => ({
code: "code",
tabSize: 8
}),
methods: {
highlighter(code) {
// js highlight example
return Prism.highlight(code, Prism.languages.js, "js");
}
}
});
</script>
</body>
</html>

Polymer2.0- is it possible to get the complete DOM content with Shaow DOM to download?

Iam trying to download the custom element after it is being updated with edit option
https://codepen.io/nagasai/pen/PKNeMw
In the above example, I am able download file with x-foo custom element but when I edit the value of it and try to download , I can see only DOM content and without shadow DOM
HTML:
<head>
<base href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/">
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="paper-input/paper-input.html">
<link rel="import" href="iron-icons/iron-icons.html">
<link rel="import" href="iron-collapse/iron-collapse.html">
</head>
<body>
<div id="Preview">
<x-foo></x-foo>
</div>
<dom-module id="x-foo">
<template>
<style>
.actionIcons {
position: absolute;
top: 0;
right: 0;
opacity: 0;
background: grey;
}
div.actionIcons iron-icon {
padding: 7px;
}
div.actionIcons iron-icon:hover {
background: lightblue;
}
.actionIcons:hover {
opacity: 1;
}
</style>
Hover Top Right hand hover to edit
<div class="actionIcons">
<iron-icon icon="icons:create" on-click="toggle"></iron-
icon>
<iron-icon icon="icons:content-copy"></iron-icon>
<iron-icon icon="icons:close" onclick="deleteElem(event)">
</iron-icon>
</div>
[[text]]
<paper-input value="{{text::input}}"></paper-input>
<iron-collapse id="collapse">
Enter field name: <paper-input type="text" value="
{{text::input}}" autofocus></paper-input>
</iron-collapse>
</template>
</dom-module>
<button onclick="downloadHtml()"><a id="downloadHtmlElem"
download>Download HTML</a></button>
</body>
JS:
class XFoo extends Polymer.Element {
static get is() { return 'x-foo'; }
static get properties() {
return {};
}
toggle() {
this.$.collapse.toggle();
}
}
customElements.define(XFoo.is, XFoo);
let downloadHtml = () =>{
let a = document.getElementById('downloadHtmlElem')
a.download = "index.html";
a.href = "data:text/text," + document.getElementById("Preview").innerHTML;
}
DOM under the shadow Root, or the shadow DOM, can not be accessed via innerHTML. It is not supposed to be. Just the way it is designed to work.
Unless you are designing your custom element and expose the DOM via Slots.
Or, the published element exposes its DOM somehow.
You could possibly try hacky ways like the one mentioned here
But a direct innerHTML on the parent DIV wouldn't get you what you want.
Also, Leaving the same answer at Your exact same query with references to earlier Stack Overflow discussions on piercing the Shadow DOM

Embedding a Google map in a Rails project

I'm confused as to where exactly place the script tags in my Rails app to have a Google map embed in a page. I'm following the directions from the Google API https://developers.google.com/maps/documentation/javascript/tutorial
The code looks like this:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map-canvas { height: 100% }
</style>
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAK04aYSxZArPElFFZfo3o2p-CbviPzfhc&sensor=false">
</script>
<script type="text/javascript">
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"/>
</body>
</html>
I'm placing the first script tag within my application.html.erb file like so:
<%= javascript_include_tag "https://maps.googleapis.com/maps/api/js?key=AIzaSyAK04aYSxZArPElFFZfo3o2p-CbviPzfhc&sensor=false" %>
I have a Venue model and a venues controller.
I want the map to appear in the Venues show action. So I place the second script inside venue.js. My show.html.erb looks like this:
<div class="center">
<h1><%= #venue.name %></h1>
<address><%= #address %></address>
<div id="map-canvas"/>
</div>
But no map appears when I load this page.
A very easy way to do this is to simply embed the map in an iframe. Using .haml for markup,
%iframe.google-location{ frameborder: '0', scrolling: 'no', src: 'https://www.google.com/maps/embed/v1/place?q=place_id:{google_generated_placeId}' }
the class 'google-location' (or whatever you want to name it) only needs to have the size of the iframe.
(make sure to have a valid api key)

Creating Pinterest like layout in ASP.NET webform

I am creating a Pinterest like layout in ASP.NET webform and I followed following two tutorials
Creating Pinetrest like Layout in ASP.NET
How to use Masonry
However, I made changes in the first tutorial based on second and I am getting below output
Clearly, this isn't what I was looking. The gap between two rows and columns is high.
Below is my code:
<
style type="text/css">
body
{
background-color:#EEEEEE;
}
#imgLoad
{
position:fixed;
bottom:0;
left:40%;
display:none;
}
.item {
width: 220px;
margin: 10px;
float: left;
background-color:honeydew;
}
</style>
<div id="container" class="transitions-enabled infinite-scroll clearfix">
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div class="item">
<img src="<%# Eval("Url") %>" />
<p><%# Eval("Description") %></p>
</div>
</ItemTemplate>
</asp:Repeater>
</div>
How do I fix it?
I believe this is related to the height, may be the row height of repeater control takes the highest among the column.
I did tried to do it with ASp.NET MVC
Controller
IEnumerable<Product> model = ProductRepository.GetData(1, 25);
return View(model);
View
<!--[if lt IE 9]><script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<style type="text/css">
.item {
width: 220px;
margin: 5px;
float: left;
background-color:honeydew;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
<script src="Scripts/Mansory.js" type="text/javascript"></script>
<script type="text/javascript">
var $container = $('#container');
$container.imagesLoaded(function () {
$container.masonry({
itemSelector: '.item',
columnWidth: 100,
isAnimated: false
});
});
</script>
#foreach (var item in Model) {
<div class="item">
<img src="#(item.Url)" />
#Html.DisplayFor(modelItem => item.Description)
</div>
}
but same result
EDIT 1
I have changed my script to
<script type="text/javascript">
$(function () {
var $container = $('#container');
$container.masonry({
itemSelector: '.item',
columnWidth: 240,
isAnimated: false
});
});
</script>
and code to
#foreach (var item in Model) {
<div id="container">
<div class="item">
<img src="#(item.Url)" />
#Html.DisplayFor(modelItem => item.Description)
</div>
</div>
}
but same result
Ok, a few things:
You have spelled "Masonry" wrong when initializing the script
Put a div with Id "container" around your items list
In stead of using $container.imagesLoaded make the whole javascript section run when page is loaded
Like this:
$(function(){
var $container = $('#container');
$container.masonry({
itemSelector: '.item',
columnWidth: 240,
isAnimated: false
});
});
Then it should work.
This is small library which implements Pinterest layout. Filling the grid goes from left to right. Count of columns can be customized in config for each resolution. Columns adaptive changes on resize. Image can be at up or down of pin.
https://github.com/yury-egorenkov/pins-grid

dojo borderlayout show all the content , flicker then redraw correctly

I copied an example from the dojo site using Borderlayout. However, when I load in the browser , the entire data is shown for all the section . Then after a few second the content is refersh and the data is displayed correctly.
here is code that i copied . Thanks for your help
<head>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dijit/themes/tundra/tundra.css">
<style type="text/css">
body, html { font-family:helvetica,arial,sans-serif; font-size:90%; }
</style>
<style type="text/css">
html, body { width: 100%; height: 100%; margin: 0; } #borderContainer
{ width: 100%; height: 100%; }
</style>
</head>
<body class="tundra ">
<div dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="true"
liveSplitters="true" id="borderContainer">
<div dojoType="dijit.layout.ContentPane" splitter="true" region="leading"
style="width: 100px;">
Hi
</div>
<div dojoType="dijit.layout.ContentPane" splitter="true" region="center">
Hi, I'm center
</div>
</div>
</body>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/dojo.xd.js"
djConfig="parseOnLoad: true">
</script>
<script type="text/javascript">
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout.BorderContainer");
</script>
<!-- NOTE: the following script tag is not intended for usage in real
world!! it is part of the CodeGlass and you should just remove it when
you use the code -->
<script type="text/javascript">
dojo.addOnLoad(function() {
if (window.pub) {
window.pub();
}
});
</script>
This looks a bit upside down : you should put your javascripts in the head section and load the dojo libraries in first place. That's not your problem though.
What happens is that when the page loads, dojo loads all the modules that you "dojo.require", then parses all your tags containing the attribute "dojoType" and processes them for rendering, and this takes time.
So the flickering that you're seeing is the difference between the page before and after the widgets are parsed.
You should add a preloader div and hide it once the page is parsed (see this example).
This is what it would look like for your example :
<html>
<head>
<title>Preloader example</title>
<!– every Dijit component needs a theme –>
<link rel="stylesheet"
href="http://o.aolcdn.com/dojo/1.4/dijit/themes/soria/soria.css">
<style type="text/css">
#preloader,
body, html {
width:100%; height:100%; margin:0; padding:0;
}
#preloader {
width:100%; height:100%; margin:0; padding:0;
background:#fff
url(’http://search.nj.com/media/images/loading.gif’)
no-repeat center center;
position:absolute;
z-index:999;
}
#borderContainer {
width:100%; height:100%;
}
</style>
<!– load Dojo, and all the required modules –>
<script src="http://o.aolcdn.com/dojo/1.4/dojo/dojo.xd.js"></script>
<script type="text/javascript">
var hideLoader = function(){
dojo.fadeOut({
node:"preloader",
onEnd: function(){
dojo.style("preloader", "display", "none");
}
}).play();
}
dojo.addOnLoad(function(){
// after page load, load more stuff (spinner is already spinning)
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.ContentPane");
dojo.require("dojo.parser");
// notice the second onLoad here:
dojo.addOnLoad(function(){
dojo.parser.parse();
hideLoader();
});
});
</script>
</head>
<body class="soria">
<div id="preloader"></div>
<div dojoType="dijit.layout.BorderContainer" id="borderContainer" design="sidebar" gutters="true" liveSplitters="true">
<div dojoType="dijit.layout.ContentPane" splitter="true" region="leading" style="width: 100px;">Hi</div>
<div dojoType="dijit.layout.ContentPane" splitter="true" region="center">I'm Center</div>
</div>
</body>
</html>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/dojo.xd.js"></script>
if(dojo.isIE){
addEvent(window, 'load', function(event) {
dojo.parser.parse();
});
}else{
dojo.addOnLoad(function(){
dojo.addOnLoad(function(){
dojo.parser.parse();
});
});
}
function addEvent( obj, type, fn ) {
if ( obj.attachEvent ) {
obj['e'+type+fn] = fn;
obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
obj.attachEvent( 'on'+type, obj[type+fn] );
} else
obj.addEventListener( type, fn, false );
}
disable parseOnLoad and manually add event to parse widgets for ie.