github.com/aarzilli/tools@v0.0.0-20151123112009-0d27094f75e0/net/http/htmlfrag/html.go (about)

     1  // Package htmlfrag contains convenience functions to generate html fragments.
     2  package htmlfrag
     3  
     4  import (
     5  	"bytes"
     6  	"fmt"
     7  	"io"
     8  	"net/http"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/pbberlin/tools/stringspb"
    13  )
    14  
    15  var sp func(format string, a ...interface{}) string = fmt.Sprintf
    16  
    17  // GetSpanner is a simple helper to output
    18  //  aligned html elements
    19  //  for backend or debug pages
    20  //  where the template package is not imperative
    21  func GetSpanner() func(interface{}, int) string {
    22  
    23  	cntr := 0
    24  	style := `
    25  		<style>
    26  			.ib {
    27  				vertical-align:middle;
    28  				display:inline-block;
    29  				width:95px;
    30  			}
    31  		</style>
    32  	`
    33  	return func(i interface{}, w int) string {
    34  
    35  		s1 := fmt.Sprint(i)
    36  		sw := fmt.Sprint(w)
    37  		s2 := fmt.Sprintf("<span class='ib' style='width:" + sw + "px;'>" + s1 + "</span>")
    38  
    39  		if cntr < 1 {
    40  			s2 = style + "\n\n" + s2
    41  		}
    42  		cntr++
    43  
    44  		return s2
    45  	}
    46  
    47  }
    48  
    49  // Wb is a helper to write an inline block with an link inside.
    50  // If url is omitted, a newline + a chapter-header is rendered.
    51  func Wb(buf1 io.Writer, linktext, url string, descs ...string) {
    52  
    53  	wstr := func(w io.Writer, s string) {
    54  		w.Write([]byte(s))
    55  	}
    56  
    57  	if url == "" {
    58  		wstr(buf1, "<br>\n")
    59  	}
    60  
    61  	if url == "nobr" { // hack, indicating no break
    62  		url = ""
    63  	}
    64  
    65  	desc := ""
    66  	if len(descs) > 0 {
    67  		desc = descs[0]
    68  	}
    69  
    70  	const styleX = "display:inline-block; width:13%; margin: 4px 0px; margin-right:12px; vertical-align:top"
    71  
    72  	wstr(buf1, "<span style='"+styleX+"'>\n")
    73  	if url == "" {
    74  		wstr(buf1, "\t<b>"+linktext+"</b>\n")
    75  	} else {
    76  		wstr(buf1, "\t<a target='_app' href='"+url+"' >"+linktext+"</a>\n")
    77  		if desc != "" {
    78  			wstr(buf1, "<br>\n ")
    79  			wstr(buf1, "<span style='"+styleX+";width:90%;font-size:80%'>\n")
    80  			wstr(buf1, desc)
    81  			wstr(buf1, "</span>\n")
    82  		}
    83  	}
    84  	wstr(buf1, "</span>\n")
    85  }
    86  
    87  // CSSColumnsWidth creates CSS classes with w[1...nCols]
    88  //  for any number of screen widths
    89  //  Thus you can write <div class='w2'> ...
    90  //  and you get an element 2/nCols wide
    91  //  and adapting to changes in the browser window
    92  //  CSS class wmax equals the largest wx class.
    93  //  CSS class wn   holds  the simple column minus a system wide margin, currently 10 pix
    94  func CSSColumnsWidth(nCols int) string {
    95  
    96  	// this is not really for the vertical scrollbar
    97  	// but some slack is required, I don't know why
    98  	// to prevent too early wrapping of blocks
    99  	const wScrollbar = 16
   100  
   101  	// this should not be required either
   102  	// since we use 'box-sizing: border-box;'
   103  	// to internalize all paddings and margins and borders :(
   104  	const wMarginsPaddings = 10
   105  
   106  	ret := new(bytes.Buffer)
   107  
   108  	// the stepping is the max wasted space
   109  	for w := 600; w <= 1600; w = w + 50 {
   110  
   111  		ret.WriteString(sp("\n\t@media (min-width: %vpx) {\n\t\t", w))
   112  		//ret.WriteString(sp("\n\t@media (min-device-width: %vpx) {\n\t\t", w))
   113  
   114  		colWidthGross := (w - wScrollbar) / nCols
   115  		colWidthNet := colWidthGross - wMarginsPaddings
   116  
   117  		s := sp(".wn  { width: %vpx; } ", colWidthNet)
   118  		ret.WriteString(s)
   119  
   120  		for c := 1; c <= nCols; c++ {
   121  			s := sp(".w%v{ width: %vpx; } ", c, c*colWidthGross)
   122  			ret.WriteString(s)
   123  		}
   124  		s2 := sp(".wmax{ width: %vpx; } ", nCols*colWidthGross)
   125  		ret.WriteString(s2)
   126  
   127  		ret.WriteString("\n\t}")
   128  
   129  	}
   130  
   131  	return fmt.Sprintf("  /* generated by htmlfrag.CSSColumnsWidth()*/ \n%v\n", ret)
   132  }
   133  
   134  // CSSColumnsHeight is similar to ...Width except:
   135  // 'min-height' attributes are generated
   136  func CSSRowsHeight(nRows int) string {
   137  
   138  	// This is so revolting -
   139  	// but since the logic is still in development, it prevents duplicate code
   140  	s := CSSColumnsWidth(nRows)
   141  
   142  	var widthToHeight = strings.NewReplacer("wn", "hn",
   143  		"wmax", "hmax",
   144  		"w1", "h1",
   145  		"w2", "h2",
   146  		"w3", "h3",
   147  		"w4", "h4",
   148  		"w5", "h5",
   149  		"w6", "h6",
   150  		"w7", "h7",
   151  		"w8", "h8",
   152  		"min-width", "min-height",
   153  		"width", "min-height")
   154  	s = widthToHeight.Replace(s)
   155  
   156  	return s
   157  }
   158  
   159  func SetNocacheHeaders(w http.ResponseWriter) {
   160  
   161  	w.Header().Set("Expires", "Mon, 26 Jul 1990 05:00:00 GMT")
   162  
   163  	tn := time.Now()
   164  	tn = tn.Add(-10 * time.Second)
   165  	tns := tn.Format(http.TimeFormat)
   166  	w.Header().Set("Last-Modified", tns)
   167  	w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate")
   168  	w.Header().Set("Cache-Control", "post-check=0, pre-check=0")
   169  	w.Header().Set("Pragma", "no-cache")
   170  
   171  	// if plainOrHtml {
   172  	// 	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
   173  	// } else {
   174  	// 	w.Header().Set("Content-Type", "text/html; charset=utf-8")
   175  	// }
   176  
   177  }
   178  func CacheHeaders(w http.ResponseWriter) {
   179  
   180  	w.Header().Set("Cache-control", "max-age=2592000") //30days (60sec * 60min * 24hours * 30days)
   181  	w.Header().Set("Cache-control", "public")
   182  
   183  	tn := time.Now()
   184  	tn = tn.Add(-1 * 24 * 365 * time.Hour)
   185  	tns := tn.Format(http.TimeFormat)
   186  	w.Header().Set("Last-Modified", tns)
   187  	// w.Header().Set("Date", tns)
   188  
   189  }
   190  
   191  func CookieDump(r *http.Request) string {
   192  	str := ""
   193  	c := r.Cookies()
   194  	for _, v := range c {
   195  		s := fmt.Sprintf("%v", v)
   196  		s = stringspb.Ellipsoider(s, 50)
   197  		str += fmt.Sprintf("%v<br>\n", s)
   198  	}
   199  	return str
   200  }