I have this multiplayer board game project, which has a Board (being the Collection) and many Piece objects (being the Model)*.
In order to display same board set up to all online players, how can I organize my Backbone code to update the Piece's position CSS attribute after a player moves that said Piece?
Additional info:
I'm using the Django framework on the server side, where every Piece object has a id, x_position and y_position attributes.
You could use CSS classes on the piece. Assuming your x_position is a range of a-z and your y_position is a range of 1-8 then
<div class="pawn <%= x_position+y_position %>">pawn</div>
And your CSS could look like
a1 { left:0; bottom:0; }
a2 { left:0; bottom:1em; }
/* and so on */
b1 { left:1em; bottom:0; }
/* and so on */
Listen to your draggable's stop event and work out which square it's in (it will provide you with the dropped position in the ui object (ui.position.left and ui.position.top). You can then apply the correct CSS class update the model, and clear the attributes the draggable has set.
Related
I am currently working on a page using NextJs and TailwindCss. The user has the ability of loading an image locally and setting the number of pieces horiz/vert (rows/cols) that they wish the image to be split in. To properly display this, I need to set the grid to the proper number of columns in the parent element.
I have an API I call locally that uses sharp to perform the split and calculate the width and height and I sort the images in my array so that they are in order since it is async. I then also generate a dynamic class string that just populates the proper number of columns for later assignment to my parent grid elements class.
CLASS STRING POPULATION
const gridClass = `grid grid-cols-${numCols} gap-2 pt-2`;
//*** At this point, the value of gridClass, if columns were set to 3, using template literals is :
'grid grid-cols-3 gap-2 pt-2'
//The proper string is now populated and passed back in the API response via classCss key
res.status(200).json({ msg: 'Success splitting', tileData: tiles, classCss: gridClass})
PAGE SNIPPET:
<div id="final">
<div className={tileCss} > //<--This is where I pull in the generated class string
{
imageData.map((nft, i)=>(
<div key={i} className='border shadow rounded-x1 overflow-hidden'>
<Image src={nft.imgSrc} alt="image" layout="responsive" width={nft.tileDimX} height={nft.tileDimY}/>
</div>
))
}
</div>
</div>
This sometimes works but other times it doesn't. Usually if I set the columns to 3, it seems to work properly, but if I set it to 5 lets say, regardless of the input image size, it just puts them all in a single column with large images. Oddly however, the parent grid class on the page is correct, it just seems that it isn't adhered to. I will provide some snapshots below to show what I'm talking about. I've been trying to figure this out for a couple days, however I haven't had luck and since I'm new to NextJs I thought I would share here and see if I'm just doing something stupid. Thanks!
The below results also don't seem to care if the viewing window is stretched wide or reduced in size. I just took the snapshots below so that you could see what was happening in a smaller viewing window.
This is the expected result where the image columns should match the columns entered by the user:
Notice how the css class shows up under styles as well:
This is the improper result, where the user selected 5 columns, the image was split into the correct number of columns, but the display of this in the front end grid does not follow the css.
As you can see grid-cols-5 is correct from a class standpoint, but the viewed result doesn't adhere to this.
Grid-cols-5 is in html class but missing under styles applied:
So I finally found the source to the issue. It seems that tailwindcss performs an optimization on classes brought in and if you are not using the class anywhere in your html, it doesn't include those classes. So I not only needed to return my dynamic string with the expected class, but I also needed to add all the classes I would possibly be using into my tailwind.config.js file under the safelist key.
So my config now looks like this and it is working as expected:
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
],
safelist: [
{
pattern: /grid-cols-./,
}
],
theme: {
extend: {},
},
plugins: [],
}
More information can be found here:
https://tailwindcss.com/docs/content-configuration#using-regular-expressions
Thanks again Mohit for your assistance.
One of the problem I noticed is in grid-cols-${numCols} in the line
const gridClass = `grid grid-cols-${numCols} gap-2 pt-2`;
TailwindCSS doesn't allow you to generate classes dynamically. So when you use the following to generate the class… grid-cols-${numCols} as a string.
…TailwindCSS will not pick that up as a valid TailwindCSS class and therefore will not produce the necessary CSS.
You can use the function from where you are getting numCols and instead of returning the value of numCols, simply return grid-cols-${numCols}.
Suppose let say your function be getNumofCols(), then modify it like this
function getNumofCols() {
...
...
...
...
...
return "grid-cols-" + numCols ;
}
So that it returns the complete string .
And use it like again
const gridClass = `grid ${getNumofCols()} gap-2 pt-2`;
If your function uses any parameter then you can create a new function and call this function and just add grid-cols- to the return value.
By doing it this way, the entire string for every class is in your source code, so Tailwind will know to generate the applicable CSS.
Is it possible for the filter property, applied to a styles object in React to have multiple filter values set?
saturation = 25;
blurAmount = 5;
brightness = 25;
opacity = 0.85;
let styles = {
backgroundImage: `url(${imageUrl})`,
WebkitFilter: `brightness(${brightness}%) saturation(${saturation}%) blur(${blurAmount}px)`,
filter: `brightness(${brightness}%) saturation(${saturation}%) blur(${blurAmount}px)`,
opacity: opacity
};
In the code above, only the opacity and backgroundImage properties get set correctly when I add the inline style to my component.
React does not support all the CSS properties so my best suggestion is you can use 3rd party library like this one https://github.com/iyegoroff/react-native-color-matrix-image-filters#supported-filters
checkout this lib I think this will help you.
I a solution I found was to give the element an ID, and set the ID to something that's associated with the color.
Example:
<img id={Log.serv} src="RadioWaves.png"/>
Log is a variable, that has dynamic input. Serv being severity (the color).
Now what you can do is on a CSS sheet, you can apply the filter to elements that have that ID.
Example:
#AllSystemsGo{
filter: invert(95%) sepia(79%) saturate(992%) hue-rotate(33deg) brightness(103%) contrast(98%);
}
You could substitute an ID with a separate classname, either way, works. I did not want to install a separate lib, so this what I came up with.
I have the following classes:
.at-icon.at-icon {}
And I need to style each element (Social network icon), that uses those classes, like this:
.at-icon.at-icon:nth-child(even) { fill: red !important }
.at-icon.at-icon:nth-child(odd) { fill: blue !important }
So one element would be red, and the other one would be blue. They all appear like this currently:
Screenshot
And my HTML using the class is:
Copy Link
The problem is: I don't have any <li> (List) in the DOM.
Unfortunately, this is all I can post here to reproduce my issue, as I'm using a third party tool, this one addthis.com
It's a free tool, you can use it for testing. I can't use it for testing as it would mean using my account resources and I might be going against their TOS.
I think what you are looking for is the descendant combinator.
What you could do is find the nearest parents of these <svg> elements that are siblings of one another, from what I can tell from your screenshot, these could be the <a> elements with the class at-share-btn applied to them.
Then, use those elements to identify the even and odd instances.
.at-share-btn:nth-child(even) {
}
.at-share-btn:nth-child(odd) {
}
After that, using the descendant combinator, target the <svg> elements within these <a> elements.
.at-share-btn:nth-child(even) .at-icon {
fill: red !important;
}
.at-share-btn:nth-child(odd) .at-icon {
fill: blue !important;
}
I'm still using 4.1 and I'm trying to center a form content on screen.
When I add a new form it stays on the "left" of the screen.
I've tried to change form.html (temmplates/shared) adding a div with a style like this:
margin-left : 10%; margin-right : 10%;
up next to the form tag and closing it at the bottom.
The form goes to the right but not centered at all.
Anyone has any clue to help with this ?
Here is a screenshot of a simple Form (it's not basec on models)
thanks
Alejandro
Ok - i've gone to a default of atk4.2 to demonstrate.
If you add a new page with defaults as follows
<?php
class page_test extends Page {
function init() {
parent::init();
$p=$this;
$f=$p->add('MVCForm')->setModel('Customer');
}
}
?>
I get the following and the fields extend across the whole width of the page.
This is because the default page template takes the whole width and is expected.
In order to adjust the form, you can use view functionality so create a view under the /lib/View directory called Centre.php and put the following code in it
<?php
class View_Centre extends View {
function init(){
parent::init();
}
function defaultTemplate() {
return array('view/centre');
}
}
?>
Then create a new template for the view in yoursite/templates/default/view called centre.html and insert the following html code
<div style='width:50%; margin: auto;'>
<?$Content?>
</div>
and then in the page, we add the view first and the form into the view rather than straight into the page.
<?php
class page_test extends Page {
function init() {
parent::init();
$p=$this;
$v=$p->add('View_Centre');
$f=$v->add('MVCForm')->setModel('Customer');
}
}
?>
and this results in the following web page
The base ATK4 form is itself a view which means you can style the form however you want so if you get for example use a different style of form such as the one described here you can do this by copying yoursite/atk4/atk4/templates/shared/form.html to yoursite/atk4/templates/shared.form.html and changing the second line from
<?form?>
<div id="<?$_name?>" class="atk-form <?$class?>" style="<?$style?>">
<?$hint?>
<form class="<?$form_internal_class?>" id="<?$form_name?>" name="<?$form_name?>" action="<?$form_action?>" method="POST" <?$enctype?>>
<fieldset class="<?$fieldset?>">
to
<?form?>
<div id="stylized>" class="myform <?$class?>" style="<?$style?>">
<?$hint?>
<form class="<?$form_internal_class?>" id="<?$form_name?>" name="<?$form_name?>" action="<?$form_action?>" method="POST" <?$enctype?>>
<fieldset class="<?$fieldset?>">
Create a new form.css file in yoursite/templates/default/css which contains the styling
Copy yoursite/atk4/templates/shared/shared.html to yoursite/templates/shared/shared.html and add an extra tag
<?$css_include?>
just above the existing
<?$js_include?>
and in Frontend.php, let every page find the new css file.
$this->addLocation('templates',array(
'css'=>array(
'default/css',
),
));
$this->template->appendHTML('css_include','<link type="text/css" href="'.$this->api->locateURL('css','form.css').'" rel="stylesheet">');
which results in a styled form like this
There are some examples of different form layouts here that you can use to adjust the form layout itself. Not sure from your question if you want to center the form in the page or centre the fields.
If you just want to centre the Form within the webpage, you want to use margin: auto for centering css rather than setting a percentage on each side as shown here
Also note, if you amend files from the atk4 directory, you should make a copy into yoursite/templates/shared and amend it there so you can upgrade by overwriting the atk4 directory later without losing anything.
If i use the default form template (in this case in a CRUD), i get the following
If i make your change to the atk4/templates/form.html by adding
<div style="width: 50%; margin: 0 auto;">
as the second line in form.html and adding the corresponding
</div>
one line from the bottom, it shifts everything slightly to the right as follows
What is unclear in your question is what you are trying to achieve - do you want to move the fields within the form or do you want to centre the whole form on the page ?
I think the reason for the shifting is because of setting the width to 50% but I dont know what layout you are trying to obtain - do you just want to right align the labels to the fields maybe ? Please post screenshots in the original question of what you are getting and try to describe what you want to achieve.
I'm making a responsive site and need to include a Facebook Like-Box for the client's Facebook fanpage. The developer page for the like-box has a widget for customization, but it doesn't allow you to set a width in percentages.
I've searched around and the closest I've got was this page from 2010, which refers to a fb:fan widget that allows you to link custom CSS. I tried to get this tutorial to work but it fails with this error:
<fb:fan> requires one of the "id" or "name" attributes.
So, to recap, I need a Facebook Like Box that I can either set up to be fluid, or which allows me to pass custom CSS to the iFrame it generates. Anyone able to point me in the right direction?
I found this Gist today and it works perfectly: https://gist.github.com/2571173
/* Make the Facebook Like box responsive (fluid width)
https://developers.facebook.com/docs/reference/plugins/like-box/ */
/* This element holds injected scripts inside iframes that in
some cases may stretch layouts. So, we're just hiding it. */
#fb-root {
display: none;
}
/* To fill the container and nothing else */
.fb_iframe_widget, .fb_iframe_widget span, .fb_iframe_widget span iframe[style] {
width: 100% !important;
}
You thought it couldn't be done? AHA! Have at you, Facebook and your wicked fixed-width ways: I wrote a JQuery script to undo all your evil!
$(document).ready(function(){
var fbWidth;
function attachFluidLikeBox(){
// the FBML markup: WIDTH is a placeholder where we'll insert our calculated width
var fbml = '<fb:like-box href="http://www.facebook.com/YOURFANPAGEORWHATEVS" width="WIDTH" show_faces="false" stream="true"></fb:like-box>';//$('#likeBoxTemplate').text().toString();
// the containing element in which the Likebox resides
var container = $('#likebox');
// we should only redraw if the width of the container has changed
if(fbWidth != container.width()){
container.empty(); // we remove any previously generated markup
fbWidth = container.width(); // store the width for later comparison
fbml = fbml.split('WIDTH').join(fbWidth.toString()); // insert correct width in pixels
container.html(fbml); // insert the FBML inside the container
try{
FB.XFBML.parse(); // parses all FBML in the DOM.
}catch(err){
// should Facebook's API crap out - wouldn't be the first time
}
}
}
var resizeTimeout;
// Resize event handler
function onResize(){
if(resizeTimeout){
clearTimeout(resizeTimeout);
}
resizeTimeout = setTimeout(attachFluidLikeBox, 200); // performance: we don't want to redraw/recalculate as the user is dragging the window
}
// Resize listener
$(window).resize(onResize);
// first time we trigger the event manually
onResize();
});
What is does is it adds a listener to the window's resize event. When it resizes, we check the width of the Likebox' containing element, generates new XFBML code with the correct width, replaces the containing element's children with said XFBML and then trigger the Facebook API to parse the XFBML again. I added some timeouts and checks to make sure it doesn't do anything stupid and only runs when it needs to.
Much has changed since the OP.
By simply choosing iFrame and setting your width to 100%, your FB Like Box should be responsive.
Basically FB adds this to the iFrame:
style="border:none; overflow:hidden; width:100%; height:300px;".
Been struggling with the exact same problem. A quick & simple solution is to use the iframe based Facebook Like box.
<iframe class="fb-like-box" src="//www.facebook.com/plugins/likebox.php?href=http%3A%2F%2Fwww.facebook.com%2Fplatform&width=292&height=500&colorscheme=light&show_faces=true&border_color&stream=true&header=true" scrolling="no" frameborder="0" allowTransparency="true"></iframe>
Note the assigned 'fb-like-box' class and all the removed inline styles. The class for the iframe could look something like this:
.fb-like-box {
width: 100% !important;
height:500px;
border:none;
overflow:hidden;
}
Looks like it doesn't matter what the height and width are that are defined in the iframe's src tag. Just place the iframe into some fluid element like a cell in a CSS grid layout.
(includes ideas from: http://updateox.com/web-design/make-facebook-comment-and-like-box-fluid-width/)
I used the HTML5 version of Facebook Like Box and here is what worked for me:
.fb-like-box,
.fb_iframe_widget span,
.fb_iframe_widget iframe {
width:100% !important;
}
You cannot set the like-box to anything other than a pixel width. My suggestion is to place it in a DIV or SPAN that is fluid with overflow set to hidden. Sure, it's going to crop off part of the like-box, but by having the requirement of fluid, this is your best bet.
Here's a small work around that appends the HTML5 Facebook LikeBox Plugin into the DOM with a response height or width.
$(document).ready(function(){
var height = $(window).height();
var width = $(window).width();
var widget_height = parseInt((height)*0.9);
var widget_width = parseInt((height)*0.3);
var page_url = "http://www.facebook.com/Facebook";
$(".fb-plugin").append("<div class='fb-like-box'
data-href='"+page_url+"'
data-width='"+widget_width+"'
data-height='"+widget_height+"'
data-colorscheme='dark'
data-show-faces='true'
data-border-color='#222'
data-stream='true'
data-header='true'>
</div></div>");
});
The comment above from Ed and Matthias about using 100% for the iframe worked great for me. Here is my iframe code
ORIGINAL WITHOUT FIX:
<iframe src="//www.facebook.com/plugins/likebox.php?
href=https%3A%2F%2Fwww.facebook.com%2FXXXXXXXXXX&
width&height=290&colorscheme=dark&
show_faces=true&header=true&stream=false&
show_border=true&appId=XXXXXXXXXX"
scrolling="no" frameborder="0"
style="border:none; overflow:hidden; height:290px;"
allowTransparency="true"></iframe>
UPDATED WITH 100% FIX:
<iframe src="//www.facebook.com/plugins/likebox.php?
href=https%3A%2F%2Fwww.facebook.com%2FXXXXXXXXXX&
width&height=290&colorscheme=dark&
show_faces=true&header=true&stream=false&
show_border=true&appId=XXXXXXXXXX"
scrolling="no" frameborder="0"
style="border:none; overflow:hidden; height:290px;width:100%"
allowTransparency="true"></iframe>
The only change is adding "width:100%" to the style attribute of the iframe
note that the code above has "XXXXXXXXXX" in place of the unique references